| OLD | NEW |
| 1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "base/waitable_event.h" | 5 #include "base/waitable_event.h" |
| 6 | 6 |
| 7 #include "base/condition_variable.h" | 7 #include "base/condition_variable.h" |
| 8 #include "base/lock.h" | 8 #include "base/lock.h" |
| 9 #include "base/message_loop.h" | 9 #include "base/message_loop.h" |
| 10 | 10 |
| (...skipping 17 matching lines...) Expand all Loading... |
| 28 // firing a waiter and so we can store that pointer to find out which event | 28 // firing a waiter and so we can store that pointer to find out which event |
| 29 // triggered. | 29 // triggered. |
| 30 // ----------------------------------------------------------------------------- | 30 // ----------------------------------------------------------------------------- |
| 31 | 31 |
| 32 namespace base { | 32 namespace base { |
| 33 | 33 |
| 34 // ----------------------------------------------------------------------------- | 34 // ----------------------------------------------------------------------------- |
| 35 // This is just an abstract base class for waking the two types of waiters | 35 // This is just an abstract base class for waking the two types of waiters |
| 36 // ----------------------------------------------------------------------------- | 36 // ----------------------------------------------------------------------------- |
| 37 WaitableEvent::WaitableEvent(bool manual_reset, bool initially_signaled) | 37 WaitableEvent::WaitableEvent(bool manual_reset, bool initially_signaled) |
| 38 : signaled_(false), | 38 : signaled_(initially_signaled), |
| 39 manual_reset_(manual_reset) { | 39 manual_reset_(manual_reset) { |
| 40 DCHECK(!initially_signaled) << "Not implemented"; | |
| 41 } | 40 } |
| 42 | 41 |
| 43 WaitableEvent::~WaitableEvent() { | 42 WaitableEvent::~WaitableEvent() { |
| 44 DCHECK(waiters_.empty()) << "Deleting WaitableEvent with listeners!"; | 43 if (!waiters_.empty()) { |
| 44 LOG(ERROR) << "Destroying a WaitableEvent (" << this << ") with " |
| 45 << waiters_.size() << " waiters"; |
| 46 NOTREACHED() << "Aborting."; |
| 47 } |
| 45 } | 48 } |
| 46 | 49 |
| 47 void WaitableEvent::Reset() { | 50 void WaitableEvent::Reset() { |
| 48 AutoLock locked(lock_); | 51 AutoLock locked(lock_); |
| 49 signaled_ = false; | 52 signaled_ = false; |
| 50 } | 53 } |
| 51 | 54 |
| 52 void WaitableEvent::Signal() { | 55 void WaitableEvent::Signal() { |
| 53 AutoLock locked(lock_); | 56 AutoLock locked(lock_); |
| 54 | 57 |
| (...skipping 26 matching lines...) Expand all Loading... |
| 81 // ----------------------------------------------------------------------------- | 84 // ----------------------------------------------------------------------------- |
| 82 // This is an synchronous waiter. The thread is waiting on the given condition | 85 // This is an synchronous waiter. The thread is waiting on the given condition |
| 83 // variable and the fired flag in this object. | 86 // variable and the fired flag in this object. |
| 84 // ----------------------------------------------------------------------------- | 87 // ----------------------------------------------------------------------------- |
| 85 class SyncWaiter : public WaitableEvent::Waiter { | 88 class SyncWaiter : public WaitableEvent::Waiter { |
| 86 public: | 89 public: |
| 87 SyncWaiter(ConditionVariable* cv, Lock* lock) | 90 SyncWaiter(ConditionVariable* cv, Lock* lock) |
| 88 : fired_(false), | 91 : fired_(false), |
| 89 cv_(cv), | 92 cv_(cv), |
| 90 lock_(lock), | 93 lock_(lock), |
| 91 signaling_event_(NULL) { } | 94 signaling_event_(NULL) { |
| 95 } |
| 92 | 96 |
| 93 bool Fire(WaitableEvent *signaling_event) { | 97 bool Fire(WaitableEvent *signaling_event) { |
| 94 lock_->Acquire(); | 98 lock_->Acquire(); |
| 95 const bool previous_value = fired_; | 99 const bool previous_value = fired_; |
| 96 fired_ = true; | 100 fired_ = true; |
| 97 if (!previous_value) | 101 if (!previous_value) |
| 98 signaling_event_ = signaling_event; | 102 signaling_event_ = signaling_event; |
| 99 lock_->Release(); | 103 lock_->Release(); |
| 100 | 104 |
| 101 if (previous_value) | 105 if (previous_value) |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 137 | 141 |
| 138 private: | 142 private: |
| 139 bool fired_; | 143 bool fired_; |
| 140 ConditionVariable *const cv_; | 144 ConditionVariable *const cv_; |
| 141 Lock *const lock_; | 145 Lock *const lock_; |
| 142 WaitableEvent* signaling_event_; // The WaitableEvent which woke us | 146 WaitableEvent* signaling_event_; // The WaitableEvent which woke us |
| 143 }; | 147 }; |
| 144 | 148 |
| 145 bool WaitableEvent::TimedWait(const TimeDelta& max_time) { | 149 bool WaitableEvent::TimedWait(const TimeDelta& max_time) { |
| 146 const Time end_time(Time::Now() + max_time); | 150 const Time end_time(Time::Now() + max_time); |
| 151 const bool finite_time = max_time.ToInternalValue() >= 0; |
| 147 | 152 |
| 148 lock_.Acquire(); | 153 lock_.Acquire(); |
| 149 if (signaled_) { | 154 if (signaled_) { |
| 150 if (!manual_reset_) { | 155 if (!manual_reset_) { |
| 151 // In this case we were signaled when we had no waiters. Now that | 156 // In this case we were signaled when we had no waiters. Now that |
| 152 // someone has waited upon us, we can automatically reset. | 157 // someone has waited upon us, we can automatically reset. |
| 153 signaled_ = false; | 158 signaled_ = false; |
| 154 } | 159 } |
| 155 | 160 |
| 156 lock_.Release(); | 161 lock_.Release(); |
| 157 return true; | 162 return true; |
| 158 } | 163 } |
| 159 | 164 |
| 160 Lock lock; | 165 Lock lock; |
| 161 lock.Acquire(); | 166 lock.Acquire(); |
| 162 ConditionVariable cv(&lock); | 167 ConditionVariable cv(&lock); |
| 163 SyncWaiter sw(&cv, &lock); | 168 SyncWaiter sw(&cv, &lock); |
| 164 | 169 |
| 165 Enqueue(&sw); | 170 Enqueue(&sw); |
| 166 lock_.Release(); | 171 lock_.Release(); |
| 167 // We are violating locking order here by holding the SyncWaiter lock but not | 172 // We are violating locking order here by holding the SyncWaiter lock but not |
| 168 // the WaitableEvent lock. However, this is safe because we don't lock @lock_ | 173 // the WaitableEvent lock. However, this is safe because we don't lock @lock_ |
| 169 // again before unlocking it. | 174 // again before unlocking it. |
| 170 | 175 |
| 171 for (;;) { | 176 for (;;) { |
| 172 if (sw.fired()) { | 177 const Time current_time(Time::Now()); |
| 178 |
| 179 if (sw.fired() || (finite_time && current_time >= end_time)) { |
| 180 const bool return_value = sw.fired(); |
| 181 |
| 182 // We can't acquire @lock_ before releasing @lock (because of locking |
| 183 // order), however, inbetween the two a signal could be fired and @sw |
| 184 // would accept it, however we will still return false, so the signal |
| 185 // would be lost on an auto-reset WaitableEvent. Thus we call Disable |
| 186 // which makes sw::Fire return false. |
| 187 sw.Disable(); |
| 173 lock.Release(); | 188 lock.Release(); |
| 174 return true; | 189 |
| 190 lock_.Acquire(); |
| 191 Dequeue(&sw, &sw); |
| 192 lock_.Release(); |
| 193 |
| 194 return return_value; |
| 175 } | 195 } |
| 176 | 196 |
| 177 if (max_time.ToInternalValue() < 0) { | 197 if (finite_time) { |
| 198 const TimeDelta max_wait(end_time - current_time); |
| 199 cv.TimedWait(max_wait); |
| 200 } else { |
| 178 cv.Wait(); | 201 cv.Wait(); |
| 179 } else { | |
| 180 const Time current_time(Time::Now()); | |
| 181 if (current_time >= end_time) { | |
| 182 // We can't acquire @lock_ before releasing @lock (because of locking | |
| 183 // order), however, inbetween the two a signal could be fired and @sw | |
| 184 // would accept it, however we will still return false, so the signal | |
| 185 // would be lost on an auto-reset WaitableEvent. Thus we call Disable | |
| 186 // which makes sw::Fire return false. | |
| 187 sw.Disable(); | |
| 188 lock.Release(); | |
| 189 | |
| 190 lock_.Acquire(); | |
| 191 Dequeue(&sw, &sw); | |
| 192 lock_.Release(); | |
| 193 return false; | |
| 194 } | |
| 195 const TimeDelta max_wait(end_time - current_time); | |
| 196 | |
| 197 cv.TimedWait(max_wait); | |
| 198 } | 202 } |
| 199 } | 203 } |
| 200 } | 204 } |
| 201 | 205 |
| 202 bool WaitableEvent::Wait() { | 206 bool WaitableEvent::Wait() { |
| 203 return TimedWait(TimeDelta::FromSeconds(-1)); | 207 return TimedWait(TimeDelta::FromSeconds(-1)); |
| 204 } | 208 } |
| 205 | 209 |
| 206 // ----------------------------------------------------------------------------- | 210 // ----------------------------------------------------------------------------- |
| 207 | 211 |
| (...skipping 175 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 383 return true; | 387 return true; |
| 384 } | 388 } |
| 385 } | 389 } |
| 386 | 390 |
| 387 return false; | 391 return false; |
| 388 } | 392 } |
| 389 | 393 |
| 390 // ----------------------------------------------------------------------------- | 394 // ----------------------------------------------------------------------------- |
| 391 | 395 |
| 392 } // namespace base | 396 } // namespace base |
| OLD | NEW |