Index: base/synchronization/condition_variable_win.cc |
=================================================================== |
--- base/synchronization/condition_variable_win.cc (revision 113515) |
+++ base/synchronization/condition_variable_win.cc (working copy) |
@@ -12,9 +12,49 @@ |
#include "base/synchronization/lock.h" |
#include "base/time.h" |
+namespace { |
+// We can't use the linker supported delay-load for kernel32 so all this |
+// cruft here is to manually late-bind the needed functions. |
+typedef void (WINAPI *InitializeConditionVariableFn)(PCONDITION_VARIABLE); |
+typedef BOOL (WINAPI *SleepConditionVariableCSFn)(PCONDITION_VARIABLE, |
+ PCRITICAL_SECTION, DWORD); |
+typedef void (WINAPI *WakeConditionVariableFn)(PCONDITION_VARIABLE); |
+typedef void (WINAPI *WakeAllConditionVariableFn)(PCONDITION_VARIABLE); |
+ |
+InitializeConditionVariableFn initialize_condition_variable_fn; |
+SleepConditionVariableCSFn sleep_condition_variable_fn; |
+WakeConditionVariableFn wake_condition_variable_fn; |
+WakeAllConditionVariableFn wake_all_condition_variable_fn; |
+ |
+bool BindVistaCondVarFunctions() { |
+ HMODULE kernel32 = GetModuleHandleA("kernel32.dll"); |
+ initialize_condition_variable_fn = |
+ reinterpret_cast<InitializeConditionVariableFn>( |
+ GetProcAddress(kernel32, "InitializeConditionVariable")); |
+ if (!initialize_condition_variable_fn) |
+ return false; |
+ sleep_condition_variable_fn = |
+ reinterpret_cast<SleepConditionVariableCSFn>( |
+ GetProcAddress(kernel32, "SleepConditionVariableCS")); |
+ if (!sleep_condition_variable_fn) |
+ return false; |
+ wake_condition_variable_fn = |
+ reinterpret_cast<WakeConditionVariableFn>( |
+ GetProcAddress(kernel32, "WakeConditionVariable")); |
+ if (!wake_condition_variable_fn) |
+ return false; |
+ wake_all_condition_variable_fn = |
+ reinterpret_cast<WakeAllConditionVariableFn>( |
+ GetProcAddress(kernel32, "WakeAllConditionVariable")); |
+ if (!wake_all_condition_variable_fn) |
+ return false; |
+ return true; |
+} |
+ |
+} // namespace. |
+ |
namespace base { |
-// Abstract class of the pimpl, idiom. TODO(cpu): create the |
-// WinVistaCondVar once the WinXPCondVar lands. |
+// Abstract base class of the pimpl idiom. |
class ConditionVarImpl { |
public: |
virtual ~ConditionVarImpl() {}; |
@@ -24,6 +64,64 @@ |
virtual void Signal() = 0; |
}; |
+/////////////////////////////////////////////////////////////////////////////// |
+// Windows Vista and Win7 implementation. |
+/////////////////////////////////////////////////////////////////////////////// |
+ |
+class WinVistaCondVar: public ConditionVarImpl { |
+ public: |
+ WinVistaCondVar(Lock* user_lock); |
+ ~WinVistaCondVar() {}; |
+ // Overridden from ConditionVarImpl. |
+ virtual void Wait() OVERRIDE; |
+ virtual void TimedWait(const TimeDelta& max_time) OVERRIDE; |
+ virtual void Broadcast() OVERRIDE; |
+ virtual void Signal() OVERRIDE; |
+ |
+ private: |
+ base::Lock& user_lock_; |
+ CONDITION_VARIABLE cv_; |
+}; |
+ |
+WinVistaCondVar::WinVistaCondVar(Lock* user_lock) |
+ : user_lock_(*user_lock) { |
+ initialize_condition_variable_fn(&cv_); |
+ DCHECK(user_lock); |
+} |
+ |
+void WinVistaCondVar::Wait() { |
+ TimedWait(TimeDelta::FromMilliseconds(INFINITE)); |
+} |
+ |
+void WinVistaCondVar::TimedWait(const TimeDelta& max_time) { |
+ DWORD timeout = static_cast<DWORD>(max_time.InMilliseconds()); |
+ CRITICAL_SECTION* cs = user_lock_.lock_.os_lock(); |
+ |
+#if !defined(NDEBUG) |
+ user_lock_.CheckHeldAndUnmark(); |
+#endif |
+ |
+ if (FALSE == sleep_condition_variable_fn(&cv_, cs, timeout)) { |
+ DCHECK(GetLastError() != WAIT_TIMEOUT); |
+ } |
+ |
+#if !defined(NDEBUG) |
+ user_lock_.CheckUnheldAndMark(); |
+#endif |
+} |
+ |
+void WinVistaCondVar::Broadcast() { |
+ wake_all_condition_variable_fn(&cv_); |
+} |
+ |
+void WinVistaCondVar::Signal() { |
+ wake_condition_variable_fn(&cv_); |
+} |
+ |
+/////////////////////////////////////////////////////////////////////////////// |
+// Windows XP implementation. |
+/////////////////////////////////////////////////////////////////////////////// |
+ |
class WinXPCondVar : public ConditionVarImpl { |
public: |
WinXPCondVar(Lock* user_lock); |
@@ -537,7 +635,12 @@ |
*/ |
ConditionVariable::ConditionVariable(Lock* user_lock) |
- : impl_(new WinXPCondVar(user_lock)) { |
+ : impl_(NULL) { |
+ static bool use_vista_native_cv = BindVistaCondVarFunctions(); |
+ if (use_vista_native_cv) |
+ impl_= new WinVistaCondVar(user_lock); |
+ else |
+ impl_ = new WinXPCondVar(user_lock); |
} |
ConditionVariable::~ConditionVariable() { |