| 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/condition_variable.h" | 5 #include "base/synchronization/condition_variable.h" |
| 6 | 6 |
| 7 #include <windows.h> | 7 #include <windows.h> |
| 8 #include <stack> | 8 #include <stack> |
| 9 | 9 |
| 10 #include "base/compiler_specific.h" | 10 #include "base/compiler_specific.h" |
| 11 #include "base/logging.h" | 11 #include "base/logging.h" |
| 12 #include "base/synchronization/lock.h" | 12 #include "base/synchronization/lock.h" |
| 13 #include "base/time.h" | 13 #include "base/time.h" |
| 14 | 14 |
| 15 namespace { |
| 16 // We can't use the linker supported delay-load for kernel32 so all this |
| 17 // cruft here is to manually late-bind the needed functions. |
| 18 typedef void (WINAPI *InitializeConditionVariableFn)(PCONDITION_VARIABLE); |
| 19 typedef BOOL (WINAPI *SleepConditionVariableCSFn)(PCONDITION_VARIABLE, |
| 20 PCRITICAL_SECTION, DWORD); |
| 21 typedef void (WINAPI *WakeConditionVariableFn)(PCONDITION_VARIABLE); |
| 22 typedef void (WINAPI *WakeAllConditionVariableFn)(PCONDITION_VARIABLE); |
| 23 |
| 24 InitializeConditionVariableFn initialize_condition_variable_fn; |
| 25 SleepConditionVariableCSFn sleep_condition_variable_fn; |
| 26 WakeConditionVariableFn wake_condition_variable_fn; |
| 27 WakeAllConditionVariableFn wake_all_condition_variable_fn; |
| 28 |
| 29 bool BindVistaCondVarFunctions() { |
| 30 HMODULE kernel32 = GetModuleHandleA("kernel32.dll"); |
| 31 initialize_condition_variable_fn = |
| 32 reinterpret_cast<InitializeConditionVariableFn>( |
| 33 GetProcAddress(kernel32, "InitializeConditionVariable")); |
| 34 if (!initialize_condition_variable_fn) |
| 35 return false; |
| 36 sleep_condition_variable_fn = |
| 37 reinterpret_cast<SleepConditionVariableCSFn>( |
| 38 GetProcAddress(kernel32, "SleepConditionVariableCS")); |
| 39 if (!sleep_condition_variable_fn) |
| 40 return false; |
| 41 wake_condition_variable_fn = |
| 42 reinterpret_cast<WakeConditionVariableFn>( |
| 43 GetProcAddress(kernel32, "WakeConditionVariable")); |
| 44 if (!wake_condition_variable_fn) |
| 45 return false; |
| 46 wake_all_condition_variable_fn = |
| 47 reinterpret_cast<WakeAllConditionVariableFn>( |
| 48 GetProcAddress(kernel32, "WakeAllConditionVariable")); |
| 49 if (!wake_all_condition_variable_fn) |
| 50 return false; |
| 51 return true; |
| 52 } |
| 53 |
| 54 } // namespace. |
| 55 |
| 15 namespace base { | 56 namespace base { |
| 16 // Abstract class of the pimpl, idiom. TODO(cpu): create the | 57 // Abstract base class of the pimpl idiom. |
| 17 // WinVistaCondVar once the WinXPCondVar lands. | |
| 18 class ConditionVarImpl { | 58 class ConditionVarImpl { |
| 19 public: | 59 public: |
| 20 virtual ~ConditionVarImpl() {}; | 60 virtual ~ConditionVarImpl() {}; |
| 21 virtual void Wait() = 0; | 61 virtual void Wait() = 0; |
| 22 virtual void TimedWait(const TimeDelta& max_time) = 0; | 62 virtual void TimedWait(const TimeDelta& max_time) = 0; |
| 23 virtual void Broadcast() = 0; | 63 virtual void Broadcast() = 0; |
| 24 virtual void Signal() = 0; | 64 virtual void Signal() = 0; |
| 25 }; | 65 }; |
| 26 | 66 |
| 67 /////////////////////////////////////////////////////////////////////////////// |
| 68 // Windows Vista and Win7 implementation. |
| 69 /////////////////////////////////////////////////////////////////////////////// |
| 70 |
| 71 class WinVistaCondVar: public ConditionVarImpl { |
| 72 public: |
| 73 WinVistaCondVar(Lock* user_lock); |
| 74 ~WinVistaCondVar() {}; |
| 75 // Overridden from ConditionVarImpl. |
| 76 virtual void Wait() OVERRIDE; |
| 77 virtual void TimedWait(const TimeDelta& max_time) OVERRIDE; |
| 78 virtual void Broadcast() OVERRIDE; |
| 79 virtual void Signal() OVERRIDE; |
| 80 |
| 81 private: |
| 82 base::Lock& user_lock_; |
| 83 CONDITION_VARIABLE cv_; |
| 84 }; |
| 85 |
| 86 WinVistaCondVar::WinVistaCondVar(Lock* user_lock) |
| 87 : user_lock_(*user_lock) { |
| 88 initialize_condition_variable_fn(&cv_); |
| 89 DCHECK(user_lock); |
| 90 } |
| 91 |
| 92 void WinVistaCondVar::Wait() { |
| 93 TimedWait(TimeDelta::FromMilliseconds(INFINITE)); |
| 94 } |
| 95 |
| 96 void WinVistaCondVar::TimedWait(const TimeDelta& max_time) { |
| 97 DWORD timeout = static_cast<DWORD>(max_time.InMilliseconds()); |
| 98 CRITICAL_SECTION* cs = user_lock_.lock_.os_lock(); |
| 99 |
| 100 #if !defined(NDEBUG) |
| 101 user_lock_.CheckHeldAndUnmark(); |
| 102 #endif |
| 103 |
| 104 if (FALSE == sleep_condition_variable_fn(&cv_, cs, timeout)) { |
| 105 DCHECK(GetLastError() != WAIT_TIMEOUT); |
| 106 } |
| 107 |
| 108 #if !defined(NDEBUG) |
| 109 user_lock_.CheckUnheldAndMark(); |
| 110 #endif |
| 111 } |
| 112 |
| 113 void WinVistaCondVar::Broadcast() { |
| 114 wake_all_condition_variable_fn(&cv_); |
| 115 } |
| 116 |
| 117 void WinVistaCondVar::Signal() { |
| 118 wake_condition_variable_fn(&cv_); |
| 119 } |
| 120 |
| 121 /////////////////////////////////////////////////////////////////////////////// |
| 122 // Windows XP implementation. |
| 123 /////////////////////////////////////////////////////////////////////////////// |
| 124 |
| 27 class WinXPCondVar : public ConditionVarImpl { | 125 class WinXPCondVar : public ConditionVarImpl { |
| 28 public: | 126 public: |
| 29 WinXPCondVar(Lock* user_lock); | 127 WinXPCondVar(Lock* user_lock); |
| 30 ~WinXPCondVar(); | 128 ~WinXPCondVar(); |
| 31 // Overridden from ConditionVarImpl. | 129 // Overridden from ConditionVarImpl. |
| 32 virtual void Wait() OVERRIDE; | 130 virtual void Wait() OVERRIDE; |
| 33 virtual void TimedWait(const TimeDelta& max_time) OVERRIDE; | 131 virtual void TimedWait(const TimeDelta& max_time) OVERRIDE; |
| 34 virtual void Broadcast() OVERRIDE; | 132 virtual void Broadcast() OVERRIDE; |
| 35 virtual void Signal() OVERRIDE; | 133 virtual void Signal() OVERRIDE; |
| 36 | 134 |
| (...skipping 493 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 530 provided O(1) performance in all required operations. Since other operations | 628 provided O(1) performance in all required operations. Since other operations |
| 531 to provide performance-and/or-fairness required queue (FIFO) and list (LIFO) | 629 to provide performance-and/or-fairness required queue (FIFO) and list (LIFO) |
| 532 containers, I would also have needed to use an STL list/queue as well as an STL | 630 containers, I would also have needed to use an STL list/queue as well as an STL |
| 533 map. In the end I decided it would be "fun" to just do it right, and I | 631 map. In the end I decided it would be "fun" to just do it right, and I |
| 534 put so many assertions (DCHECKs) into the container class that it is trivial to | 632 put so many assertions (DCHECKs) into the container class that it is trivial to |
| 535 code review and validate its correctness. | 633 code review and validate its correctness. |
| 536 | 634 |
| 537 */ | 635 */ |
| 538 | 636 |
| 539 ConditionVariable::ConditionVariable(Lock* user_lock) | 637 ConditionVariable::ConditionVariable(Lock* user_lock) |
| 540 : impl_(new WinXPCondVar(user_lock)) { | 638 : impl_(NULL) { |
| 639 static bool use_vista_native_cv = BindVistaCondVarFunctions(); |
| 640 if (use_vista_native_cv) |
| 641 impl_= new WinVistaCondVar(user_lock); |
| 642 else |
| 643 impl_ = new WinXPCondVar(user_lock); |
| 541 } | 644 } |
| 542 | 645 |
| 543 ConditionVariable::~ConditionVariable() { | 646 ConditionVariable::~ConditionVariable() { |
| 544 delete impl_; | 647 delete impl_; |
| 545 } | 648 } |
| 546 | 649 |
| 547 void ConditionVariable::Wait() { | 650 void ConditionVariable::Wait() { |
| 548 impl_->Wait(); | 651 impl_->Wait(); |
| 549 } | 652 } |
| 550 | 653 |
| 551 void ConditionVariable::TimedWait(const TimeDelta& max_time) { | 654 void ConditionVariable::TimedWait(const TimeDelta& max_time) { |
| 552 impl_->TimedWait(max_time); | 655 impl_->TimedWait(max_time); |
| 553 } | 656 } |
| 554 | 657 |
| 555 void ConditionVariable::Broadcast() { | 658 void ConditionVariable::Broadcast() { |
| 556 impl_->Broadcast(); | 659 impl_->Broadcast(); |
| 557 } | 660 } |
| 558 | 661 |
| 559 void ConditionVariable::Signal() { | 662 void ConditionVariable::Signal() { |
| 560 impl_->Signal(); | 663 impl_->Signal(); |
| 561 } | 664 } |
| 562 | 665 |
| 563 } // namespace base | 666 } // namespace base |
| OLD | NEW |