Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(964)

Unified Diff: base/waitable_event_posix.cc

Issue 53026: POSIX: allow WaitableEvents to be deleted while watching them. (Closed)
Patch Set: Addressing Jeremy's comments Created 11 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « base/waitable_event.h ('k') | base/waitable_event_watcher.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: base/waitable_event_posix.cc
diff --git a/base/waitable_event_posix.cc b/base/waitable_event_posix.cc
index 09e28684c5da7ac156b229f11f8aa88eae8ad07d..690c7557c351800eb86b0911d8f689a7335295bb 100644
--- a/base/waitable_event_posix.cc
+++ b/base/waitable_event_posix.cc
@@ -35,46 +35,40 @@ namespace base {
// This is just an abstract base class for waking the two types of waiters
// -----------------------------------------------------------------------------
WaitableEvent::WaitableEvent(bool manual_reset, bool initially_signaled)
- : signaled_(initially_signaled),
- manual_reset_(manual_reset) {
+ : kernel_(new WaitableEventKernel(manual_reset, initially_signaled)) {
}
WaitableEvent::~WaitableEvent() {
- if (!waiters_.empty()) {
- LOG(ERROR) << "Destroying a WaitableEvent (" << this << ") with "
- << waiters_.size() << " waiters";
- NOTREACHED() << "Aborting.";
- }
}
void WaitableEvent::Reset() {
- AutoLock locked(lock_);
- signaled_ = false;
+ AutoLock locked(kernel_->lock_);
+ kernel_->signaled_ = false;
}
void WaitableEvent::Signal() {
- AutoLock locked(lock_);
+ AutoLock locked(kernel_->lock_);
- if (signaled_)
+ if (kernel_->signaled_)
return;
- if (manual_reset_) {
+ if (kernel_->manual_reset_) {
SignalAll();
- signaled_ = true;
+ kernel_->signaled_ = true;
} else {
// In the case of auto reset, if no waiters were woken, we remain
// signaled.
if (!SignalOne())
- signaled_ = true;
+ kernel_->signaled_ = true;
}
}
bool WaitableEvent::IsSignaled() {
- AutoLock locked(lock_);
+ AutoLock locked(kernel_->lock_);
- const bool result = signaled_;
- if (result && !manual_reset_)
- signaled_ = false;
+ const bool result = kernel_->signaled_;
+ if (result && !kernel_->manual_reset_)
+ kernel_->signaled_ = false;
return result;
}
@@ -150,15 +144,15 @@ bool WaitableEvent::TimedWait(const TimeDelta& max_time) {
const Time end_time(Time::Now() + max_time);
const bool finite_time = max_time.ToInternalValue() >= 0;
- lock_.Acquire();
- if (signaled_) {
- if (!manual_reset_) {
+ kernel_->lock_.Acquire();
+ if (kernel_->signaled_) {
+ if (!kernel_->manual_reset_) {
// In this case we were signaled when we had no waiters. Now that
// someone has waited upon us, we can automatically reset.
- signaled_ = false;
+ kernel_->signaled_ = false;
}
- lock_.Release();
+ kernel_->lock_.Release();
return true;
}
@@ -168,7 +162,7 @@ bool WaitableEvent::TimedWait(const TimeDelta& max_time) {
SyncWaiter sw(&cv, &lock);
Enqueue(&sw);
- lock_.Release();
+ kernel_->lock_.Release();
// We are violating locking order here by holding the SyncWaiter lock but not
// the WaitableEvent lock. However, this is safe because we don't lock @lock_
// again before unlocking it.
@@ -187,9 +181,9 @@ bool WaitableEvent::TimedWait(const TimeDelta& max_time) {
sw.Disable();
lock.Release();
- lock_.Acquire();
- Dequeue(&sw, &sw);
- lock_.Release();
+ kernel_->lock_.Acquire();
+ kernel_->Dequeue(&sw, &sw);
+ kernel_->lock_.Release();
return return_value;
}
@@ -261,7 +255,7 @@ size_t WaitableEvent::WaitMany(WaitableEvent** raw_waitables,
lock.Acquire();
// Release the WaitableEvent locks in the reverse order
for (size_t i = 0; i < count; ++i) {
- waitables[count - (1 + i)].first->lock_.Release();
+ waitables[count - (1 + i)].first->kernel_->lock_.Release();
}
for (;;) {
@@ -281,12 +275,12 @@ size_t WaitableEvent::WaitMany(WaitableEvent** raw_waitables,
// remove our SyncWaiter from the wait-list
for (size_t i = 0; i < count; ++i) {
if (raw_waitables[i] != signaled_event) {
- raw_waitables[i]->lock_.Acquire();
+ raw_waitables[i]->kernel_->lock_.Acquire();
// There's no possible ABA issue with the address of the SyncWaiter here
// because it lives on the stack. Thus the tag value is just the pointer
// value again.
- raw_waitables[i]->Dequeue(&sw, &sw);
- raw_waitables[i]->lock_.Release();
+ raw_waitables[i]->kernel_->Dequeue(&sw, &sw);
+ raw_waitables[i]->kernel_->lock_.Release();
} else {
signaled_index = i;
}
@@ -312,17 +306,17 @@ size_t WaitableEvent::EnqueueMany
if (!count)
return 0;
- waitables[0].first->lock_.Acquire();
- if (waitables[0].first->signaled_) {
- if (!waitables[0].first->manual_reset_)
- waitables[0].first->signaled_ = false;
- waitables[0].first->lock_.Release();
+ waitables[0].first->kernel_->lock_.Acquire();
+ if (waitables[0].first->kernel_->signaled_) {
+ if (!waitables[0].first->kernel_->manual_reset_)
+ waitables[0].first->kernel_->signaled_ = false;
+ waitables[0].first->kernel_->lock_.Release();
return count;
}
const size_t r = EnqueueMany(waitables + 1, count - 1, waiter);
if (r) {
- waitables[0].first->lock_.Release();
+ waitables[0].first->kernel_->lock_.Release();
} else {
waitables[0].first->Enqueue(waiter);
}
@@ -343,12 +337,12 @@ bool WaitableEvent::SignalAll() {
bool signaled_at_least_one = false;
for (std::list<Waiter*>::iterator
- i = waiters_.begin(); i != waiters_.end(); ++i) {
+ i = kernel_->waiters_.begin(); i != kernel_->waiters_.end(); ++i) {
if ((*i)->Fire(this))
signaled_at_least_one = true;
}
- waiters_.clear();
+ kernel_->waiters_.clear();
return signaled_at_least_one;
}
@@ -358,11 +352,11 @@ bool WaitableEvent::SignalAll() {
// ---------------------------------------------------------------------------
bool WaitableEvent::SignalOne() {
for (;;) {
- if (waiters_.empty())
+ if (kernel_->waiters_.empty())
return false;
- const bool r = (*waiters_.begin())->Fire(this);
- waiters_.pop_front();
+ const bool r = (*kernel_->waiters_.begin())->Fire(this);
+ kernel_->waiters_.pop_front();
if (r)
return true;
}
@@ -372,14 +366,14 @@ bool WaitableEvent::SignalOne() {
// Add a waiter to the list of those waiting. Called with lock held.
// -----------------------------------------------------------------------------
void WaitableEvent::Enqueue(Waiter* waiter) {
- waiters_.push_back(waiter);
+ kernel_->waiters_.push_back(waiter);
}
// -----------------------------------------------------------------------------
// Remove a waiter from the list of those waiting. Return true if the waiter was
// actually removed. Called with lock held.
// -----------------------------------------------------------------------------
-bool WaitableEvent::Dequeue(Waiter* waiter, void* tag) {
+bool WaitableEvent::WaitableEventKernel::Dequeue(Waiter* waiter, void* tag) {
for (std::list<Waiter*>::iterator
i = waiters_.begin(); i != waiters_.end(); ++i) {
if (*i == waiter && (*i)->Compare(tag)) {
« no previous file with comments | « base/waitable_event.h ('k') | base/waitable_event_watcher.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698