diff options
author | cpu@chromium.org <cpu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-12-15 18:57:23 +0000 |
---|---|---|
committer | cpu@chromium.org <cpu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-12-15 18:57:23 +0000 |
commit | 7f19742b3390986eb3d3759ce6716444b0bfbd05 (patch) | |
tree | 23db43c8b2b42c52500bf44e1406c4d9d6af6eac /base/synchronization | |
parent | b11a9e8b8338eae31caba9874990ff9311bde749 (diff) | |
download | chromium_src-7f19742b3390986eb3d3759ce6716444b0bfbd05.zip chromium_src-7f19742b3390986eb3d3759ce6716444b0bfbd05.tar.gz chromium_src-7f19742b3390986eb3d3759ce6716444b0bfbd05.tar.bz2 |
Condition variable implementation for vista, win7
- As promised.
Strange microsoft thing: there is a function to intialize the cv but no function to unititialize it.
BUG=none
TEST=current tests suffice
Review URL: http://codereview.chromium.org/8953003
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@114670 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'base/synchronization')
-rw-r--r-- | base/synchronization/condition_variable_win.cc | 109 | ||||
-rw-r--r-- | base/synchronization/lock.h | 5 | ||||
-rw-r--r-- | base/synchronization/lock_impl.h | 4 |
3 files changed, 111 insertions, 7 deletions
diff --git a/base/synchronization/condition_variable_win.cc b/base/synchronization/condition_variable_win.cc index cd74120..4f6827f 100644 --- a/base/synchronization/condition_variable_win.cc +++ b/base/synchronization/condition_variable_win.cc @@ -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 @@ class ConditionVarImpl { 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 @@ code review and validate its correctness. */ 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() { diff --git a/base/synchronization/lock.h b/base/synchronization/lock.h index f3a685e..ceaad8d 100644 --- a/base/synchronization/lock.h +++ b/base/synchronization/lock.h @@ -62,8 +62,11 @@ class BASE_EXPORT Lock { // The posix implementation of ConditionVariable needs to be able // to see our lock and tweak our debugging counters, as it releases // and acquires locks inside of pthread_cond_{timed,}wait. - // Windows doesn't need to do this as it calls the Lock::* methods. friend class ConditionVariable; +#elif defined(OS_WIN) + // The Windows Vista implementation of ConditionVariable needs the + // native handle of the critical section. + friend class WinVistaCondVar; #endif private: diff --git a/base/synchronization/lock_impl.h b/base/synchronization/lock_impl.h index 63efc5ff..03b0c64 100644 --- a/base/synchronization/lock_impl.h +++ b/base/synchronization/lock_impl.h @@ -45,12 +45,10 @@ class BASE_EXPORT LockImpl { // a successful call to Try, or a call to Lock. void Unlock(); - // Return the native underlying lock. Not supported for Windows builds. + // Return the native underlying lock. // TODO(awalker): refactor lock and condition variables so that this is // unnecessary. -#if !defined(OS_WIN) OSLockType* os_lock() { return &os_lock_; } -#endif private: OSLockType os_lock_; |