| OLD | NEW |
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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/synchronization/waitable_event.h" | 5 #include "base/synchronization/waitable_event.h" |
| 6 | 6 |
| 7 #include "base/synchronization/condition_variable.h" | 7 #include "base/synchronization/condition_variable.h" |
| 8 #include "base/synchronization/lock.h" | 8 #include "base/synchronization/lock.h" |
| 9 #include "base/message_loop.h" | 9 #include "base/message_loop.h" |
| 10 | 10 |
| (...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 142 return &cv_; | 142 return &cv_; |
| 143 } | 143 } |
| 144 | 144 |
| 145 private: | 145 private: |
| 146 bool fired_; | 146 bool fired_; |
| 147 WaitableEvent* signaling_event_; // The WaitableEvent which woke us | 147 WaitableEvent* signaling_event_; // The WaitableEvent which woke us |
| 148 base::Lock lock_; | 148 base::Lock lock_; |
| 149 base::ConditionVariable cv_; | 149 base::ConditionVariable cv_; |
| 150 }; | 150 }; |
| 151 | 151 |
| 152 bool WaitableEvent::Wait() { | 152 void WaitableEvent::Wait() { |
| 153 return TimedWait(TimeDelta::FromSeconds(-1)); | 153 bool result = TimedWait(TimeDelta::FromSeconds(-1)); |
| 154 DCHECK(result) << "TimedWait() should never fail with infinite timeout"; |
| 154 } | 155 } |
| 155 | 156 |
| 156 bool WaitableEvent::TimedWait(const TimeDelta& max_time) { | 157 bool WaitableEvent::TimedWait(const TimeDelta& max_time) { |
| 157 const Time end_time(Time::Now() + max_time); | 158 const Time end_time(Time::Now() + max_time); |
| 158 const bool finite_time = max_time.ToInternalValue() >= 0; | 159 const bool finite_time = max_time.ToInternalValue() >= 0; |
| 159 | 160 |
| 160 kernel_->lock_.Acquire(); | 161 kernel_->lock_.Acquire(); |
| 161 if (kernel_->signaled_) { | 162 if (kernel_->signaled_) { |
| 162 if (!kernel_->manual_reset_) { | 163 if (!kernel_->manual_reset_) { |
| 163 // In this case we were signaled when we had no waiters. Now that | 164 // In this case we were signaled when we had no waiters. Now that |
| 164 // someone has waited upon us, we can automatically reset. | 165 // someone has waited upon us, we can automatically reset. |
| 165 kernel_->signaled_ = false; | 166 kernel_->signaled_ = false; |
| 166 } | |
| 167 | |
| 168 kernel_->lock_.Release(); | |
| 169 return true; | |
| 170 } | 167 } |
| 171 | 168 |
| 172 SyncWaiter sw; | 169 kernel_->lock_.Release(); |
| 173 sw.lock()->Acquire(); | 170 return true; |
| 171 } |
| 174 | 172 |
| 175 Enqueue(&sw); | 173 SyncWaiter sw; |
| 174 sw.lock()->Acquire(); |
| 175 |
| 176 Enqueue(&sw); |
| 176 kernel_->lock_.Release(); | 177 kernel_->lock_.Release(); |
| 177 // We are violating locking order here by holding the SyncWaiter lock but not | 178 // We are violating locking order here by holding the SyncWaiter lock but not |
| 178 // the WaitableEvent lock. However, this is safe because we don't lock @lock_ | 179 // the WaitableEvent lock. However, this is safe because we don't lock @lock_ |
| 179 // again before unlocking it. | 180 // again before unlocking it. |
| 180 | 181 |
| 181 for (;;) { | 182 for (;;) { |
| 182 const Time current_time(Time::Now()); | 183 const Time current_time(Time::Now()); |
| 183 | 184 |
| 184 if (sw.fired() || (finite_time && current_time >= end_time)) { | 185 if (sw.fired() || (finite_time && current_time >= end_time)) { |
| 185 const bool return_value = sw.fired(); | 186 const bool return_value = sw.fired(); |
| 186 | 187 |
| 187 // We can't acquire @lock_ before releasing the SyncWaiter lock (because | 188 // We can't acquire @lock_ before releasing the SyncWaiter lock (because |
| 188 // of locking order), however, in between the two a signal could be fired | 189 // of locking order), however, in between the two a signal could be fired |
| 189 // and @sw would accept it, however we will still return false, so the | 190 // and @sw would accept it, however we will still return false, so the |
| 190 // signal would be lost on an auto-reset WaitableEvent. Thus we call | 191 // signal would be lost on an auto-reset WaitableEvent. Thus we call |
| 191 // Disable which makes sw::Fire return false. | 192 // Disable which makes sw::Fire return false. |
| 192 sw.Disable(); | 193 sw.Disable(); |
| 193 sw.lock()->Release(); | 194 sw.lock()->Release(); |
| 194 | 195 |
| 195 kernel_->lock_.Acquire(); | 196 kernel_->lock_.Acquire(); |
| 196 kernel_->Dequeue(&sw, &sw); | 197 kernel_->Dequeue(&sw, &sw); |
| 197 kernel_->lock_.Release(); | 198 kernel_->lock_.Release(); |
| 198 | 199 |
| 199 return return_value; | 200 return return_value; |
| 200 } | 201 } |
| 201 | 202 |
| 202 if (finite_time) { | 203 if (finite_time) { |
| 203 const TimeDelta max_wait(end_time - current_time); | 204 const TimeDelta max_wait(end_time - current_time); |
| 204 sw.cv()->TimedWait(max_wait); | 205 sw.cv()->TimedWait(max_wait); |
| 205 } else { | 206 } else { |
| 206 sw.cv()->Wait(); | 207 sw.cv()->Wait(); |
| (...skipping 185 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 392 return true; | 393 return true; |
| 393 } | 394 } |
| 394 } | 395 } |
| 395 | 396 |
| 396 return false; | 397 return false; |
| 397 } | 398 } |
| 398 | 399 |
| 399 // ----------------------------------------------------------------------------- | 400 // ----------------------------------------------------------------------------- |
| 400 | 401 |
| 401 } // namespace base | 402 } // namespace base |
| OLD | NEW |