summaryrefslogtreecommitdiffstats
path: root/base/synchronization
diff options
context:
space:
mode:
authorcpu@chromium.org <cpu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-12-15 18:57:23 +0000
committercpu@chromium.org <cpu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-12-15 18:57:23 +0000
commit7f19742b3390986eb3d3759ce6716444b0bfbd05 (patch)
tree23db43c8b2b42c52500bf44e1406c4d9d6af6eac /base/synchronization
parentb11a9e8b8338eae31caba9874990ff9311bde749 (diff)
downloadchromium_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.cc109
-rw-r--r--base/synchronization/lock.h5
-rw-r--r--base/synchronization/lock_impl.h4
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_;