Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(297)

Side by Side Diff: base/synchronization/condition_variable_win.cc

Issue 8953003: Condition variable implementation for vista, win7 (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: Created 9 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | base/synchronization/lock.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
OLDNEW
« no previous file with comments | « no previous file | base/synchronization/lock.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698