[Author: andreip]
[google-gears.git] / gears / base / common / mutex.h
blobe6d4d2a88718b1c0f8161d44bfae911c0e251b40
1 // Copyright 2007, Google Inc.
2 //
3 // Redistribution and use in source and binary forms, with or without
4 // modification, are permitted provided that the following conditions are met:
5 //
6 // 1. Redistributions of source code must retain the above copyright notice,
7 // this list of conditions and the following disclaimer.
8 // 2. Redistributions in binary form must reproduce the above copyright notice,
9 // this list of conditions and the following disclaimer in the documentation
10 // and/or other materials provided with the distribution.
11 // 3. Neither the name of Google Inc. nor the names of its contributors may be
12 // used to endorse or promote products derived from this software without
13 // specific prior written permission.
15 // THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
16 // WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
17 // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
18 // EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
19 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
21 // OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
22 // WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
23 // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
24 // ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 #ifndef GEARS_BASE_COMMON_MUTEX_H__
27 #define GEARS_BASE_COMMON_MUTEX_H__
29 #include "gears/base/common/common.h" // for DISALLOW_EVIL_CONSTRUCTORS
31 // TODO(mpcomplete): implement these.
32 #if BROWSER_NPAPI && defined(WIN32)
33 #define BROWSER_IE 1
34 #endif
36 class Condition;
39 // A Mutex is a non-reentrant (aka non-recursive) mutex. At most
40 // one thread T may hold a mutex at a given time.
41 // See also MutexLock, below, for scoped Mutex acquisition.
43 class Mutex {
44 public:
45 Mutex();
46 ~Mutex();
48 void Lock();
49 void Unlock();
51 // Until the Condition is true, releases and reacquires this Mutex.
52 // The thread must already hold this Mutex when calling Await().
53 // Performance matches that of native Events (Win32) or CondVars (Firefox).
55 // A Condition "cond" used with this Mutex may be invoked an arbitrary
56 // number of times, by any thread using the Mutex. "cond" will always
57 // be invoked with the Mutex held by the thread that calls it, so it
58 // should not block for long periods or sleep on a timer. "cond" must return
59 // a boolean that is a function of state that is protected by the Mutex. Thus,
60 // if "cond" returns true just before this Mutex is released, it must also
61 // return true just after this Mutex is reacquired. "cond" MUST NOT BE A
62 // FUNCTION OF THE TIME, or of any other state not protected by the Mutex!
63 void Await(const Condition &cond);
65 private:
66 #ifdef DEBUG
67 bool is_locked_;
68 #endif // DEBUG
70 #if BROWSER_IE
71 CRITICAL_SECTION crit_sec_;
72 #elif BROWSER_FF
73 PRLock *lock_;
74 #elif BROWSER_SAFARI
75 pthread_mutex_t mutex_;
76 #endif
80 // ----------------------------------------------------------------------------
83 // MutexLock(mu) acquires mu when constructed and releases it when destroyed.
85 class MutexLock {
86 public:
87 explicit MutexLock(Mutex *mu) : mu_(mu) { this->mu_->Lock(); }
88 ~MutexLock() { this->mu_->Unlock(); }
89 private:
90 Mutex *const mu_;
91 DISALLOW_EVIL_CONSTRUCTORS(MutexLock);
93 // Catch bug where variable name is omitted, e.g. MutexLock (&mu);
94 #define MutexLock(x) COMPILE_ASSERT(0, mutex_lock_decl_missing_var_name)
97 // ----------------------------------------------------------------------------
100 // Implements a subset of the Google 'Condition' class.
102 // Any variables referenced to evaluate this Condition should be protected by
103 // the Mutex receiving this Condition.
105 // Various calls in Mutex take a Condition as argument;
106 // clients can wait for conditions to become true.
107 // Functions passed to the constructors should be pure functions;
108 // their results should depend only on the arguments and
109 // they should have no side-effects.
111 class Condition {
112 public:
113 // A Condition that returns the value of *cond.
114 explicit Condition(bool *cond)
115 : function_(reinterpret_cast<InternalFunctionType>(Dereference)),
116 arg_(cond) {}
118 // Templated versions for invoking a method that returns a bool.
119 // Usage: Condition(object, &Class::Method)
120 // Condition::Eval() returns the result of object->Method()
121 template<typename T>
122 Condition(T *object, bool (T::*method)());
123 // Same as above, for const members
124 template<typename T>
125 Condition(const T *object, bool (T::*method)() const);
127 // Evaluates the condition
128 bool Eval() const {
129 if (method_) {
130 InternalMethodCallerType caller =
131 reinterpret_cast<InternalMethodCallerType>(function_);
132 return (*caller)(arg_, method_);
134 return function_ == 0 || (*function_)(arg_);
137 private:
138 typedef bool (*InternalFunctionType)(void *);
139 typedef bool (Condition::*InternalMethodType)();
140 typedef bool (*InternalMethodCallerType)(void *, InternalMethodType);
142 static bool Dereference(bool *arg) { return *arg; }
144 template<typename T>
145 static bool ConditionMethodCaller(void *v, bool (Condition::*m)());
147 InternalFunctionType function_; // function taking void * returning bool
148 InternalMethodType method_; // method returning bool
149 void *arg_;
152 // static
153 template<typename T>
154 bool Condition::ConditionMethodCaller(void *v, bool (Condition::*m)()) {
155 typedef bool (T::*RealMethodType)();
156 T *x = static_cast<T *>(v);
157 RealMethodType rm = reinterpret_cast<RealMethodType>(m);
158 return (x->*rm)();
161 template<typename T>
162 inline Condition::Condition(T *object, bool (T::*method)()) :
163 method_(reinterpret_cast<InternalMethodType>(method)), arg_(object) {
164 InternalMethodCallerType caller = &ConditionMethodCaller<T>;
165 this->function_ = reinterpret_cast<InternalFunctionType>(caller);
168 template<typename T>
169 inline Condition::Condition(const T *object, bool (T::*method)() const) :
170 method_((InternalMethodType) method), arg_((void *) object) {
171 InternalMethodCallerType caller = &ConditionMethodCaller<T>;
172 this->function_ = reinterpret_cast<InternalFunctionType>(caller);
175 // TODO(mpcomplete): remove
176 #if BROWSER_NPAPI
177 #undef BROWSER_IE
178 #endif
180 #endif // GEARS_BASE_COMMON_MUTEX_H__