| OLD | NEW |
| (Empty) |
| 1 // Copyright 2004-2010 Google Inc. | |
| 2 // | |
| 3 // Licensed under the Apache License, Version 2.0 (the "License"); | |
| 4 // you may not use this file except in compliance with the License. | |
| 5 // You may obtain a copy of the License at | |
| 6 // | |
| 7 // http://www.apache.org/licenses/LICENSE-2.0 | |
| 8 // | |
| 9 // Unless required by applicable law or agreed to in writing, software | |
| 10 // distributed under the License is distributed on an "AS IS" BASIS, | |
| 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
| 12 // See the License for the specific language governing permissions and | |
| 13 // limitations under the License. | |
| 14 // ======================================================================== | |
| 15 // | |
| 16 // Declares some classes and macros to encapsulate | |
| 17 // the synchronization primitives. | |
| 18 | |
| 19 // TODO(omaha): remove dependency on atlstr | |
| 20 | |
| 21 #ifndef OMAHA_BASE_SYNCHRONIZED_H_ | |
| 22 #define OMAHA_BASE_SYNCHRONIZED_H_ | |
| 23 | |
| 24 #include <windows.h> | |
| 25 #include <atlstr.h> | |
| 26 #include "base/basictypes.h" | |
| 27 | |
| 28 namespace omaha { | |
| 29 | |
| 30 // This macros are used to create a unique name | |
| 31 // We need to go through two steps of expansion. | |
| 32 // Macro kMakeName1 will expand to string + number | |
| 33 // and macro kMakeName1 will put them together to create | |
| 34 // the unique name. | |
| 35 #define MAKE_NAME2(x, y) x##y | |
| 36 #define MAKE_NAME1(x, y) MAKE_NAME2(x, y) | |
| 37 #define MAKE_NAME(x) MAKE_NAME1(x, __COUNTER__) | |
| 38 | |
| 39 // Declare the interface in implement mutual | |
| 40 // exclusion. For in process mutual exclusion | |
| 41 // simple critical sections can be used. For | |
| 42 // interprocess mutual exclusion some named | |
| 43 // kernel mode object will have to be used. | |
| 44 struct Lockable { | |
| 45 virtual ~Lockable() {} | |
| 46 virtual bool Lock() const = 0; | |
| 47 virtual bool Unlock() const = 0; | |
| 48 }; | |
| 49 | |
| 50 // Scope based mutual exclusion. Locks | |
| 51 // the object on construction and unlocks | |
| 52 // during destruction. Very convinient to use | |
| 53 // with the macros __mutexScope and __mutexBlock | |
| 54 class AutoSync { | |
| 55 bool first_time_; | |
| 56 public: | |
| 57 explicit AutoSync(const Lockable *pLock); | |
| 58 explicit AutoSync(const Lockable &rLock); | |
| 59 ~AutoSync(); | |
| 60 // this function is only needed to use with | |
| 61 // the macro __mutexBlock | |
| 62 bool FirstTime(); | |
| 63 private: | |
| 64 const Lockable * lock_; | |
| 65 DISALLOW_EVIL_CONSTRUCTORS(AutoSync); | |
| 66 }; | |
| 67 | |
| 68 // the usaage: | |
| 69 // class A : public Lockable { | |
| 70 // | |
| 71 // | |
| 72 // | |
| 73 // void foo(){ | |
| 74 // __mutexScope(this); | |
| 75 // ...... | |
| 76 // ....... | |
| 77 // everything is synchronized till the end of the | |
| 78 // function or the time it returns (from any place) | |
| 79 // } // end foo. | |
| 80 // | |
| 81 // void bar() { | |
| 82 // ...... | |
| 83 // ...... do something here. | |
| 84 // ...... | |
| 85 // __mutexBlock(this){ | |
| 86 // .... do some other stuff | |
| 87 // .... | |
| 88 // .... | |
| 89 // } everything is synchronized till here | |
| 90 // | |
| 91 // }; // end class A | |
| 92 | |
| 93 // | |
| 94 #define __mutexScope(lock) AutoSync MAKE_NAME(hiddenLock)(lock) | |
| 95 #define __mutexBlock(lock) \ | |
| 96 for (AutoSync hiddenLock(lock); hiddenLock.FirstTime(); ) | |
| 97 | |
| 98 // GLock stands for global lock. | |
| 99 // Implementaion of Lockable to allow mutual exclusion | |
| 100 // between different processes. | |
| 101 // For in-process mutual exclusion use LLock - local lock | |
| 102 class GLock : public Lockable { | |
| 103 public: | |
| 104 GLock(); | |
| 105 virtual ~GLock(); | |
| 106 | |
| 107 // Create mutex returns the status of creation. Use ::GetLastError for | |
| 108 // error information. | |
| 109 bool InitializeWithSecAttr(const TCHAR* name, | |
| 110 LPSECURITY_ATTRIBUTES lock_attributes); | |
| 111 | |
| 112 // Create mutex return the status of creation. Sets to default DACL. | |
| 113 bool Initialize(const TCHAR* name); | |
| 114 | |
| 115 virtual bool Lock() const; | |
| 116 virtual bool Lock(DWORD dwMilliseconds) const; | |
| 117 virtual bool Unlock() const; | |
| 118 | |
| 119 private: | |
| 120 #if defined(DEBUG) || defined(ASSERT_IN_RELEASE) | |
| 121 CString name_; | |
| 122 #endif | |
| 123 mutable HANDLE mutex_; | |
| 124 DISALLOW_EVIL_CONSTRUCTORS(GLock); | |
| 125 }; | |
| 126 | |
| 127 // FakeGLock looks like a GLock, but none of its methods do anything. | |
| 128 // Only used with SharedMemoryPtr, in cases where locking is not required or | |
| 129 // desired. | |
| 130 class FakeGLock : public Lockable { | |
| 131 public: | |
| 132 FakeGLock() {} | |
| 133 virtual ~FakeGLock() {} | |
| 134 bool InitializeWithSecAttr(const TCHAR*, LPSECURITY_ATTRIBUTES) { | |
| 135 return true; | |
| 136 } | |
| 137 bool Initialize(const TCHAR*) { return true; } | |
| 138 virtual bool Lock() const { return true; } | |
| 139 virtual bool Lock(DWORD) const { return true; } | |
| 140 virtual bool Unlock() const { return true; } | |
| 141 | |
| 142 private: | |
| 143 DISALLOW_EVIL_CONSTRUCTORS(FakeGLock); | |
| 144 }; | |
| 145 | |
| 146 // LLock stands for local lock. | |
| 147 // means works only inside the process. | |
| 148 // use GLock - global lock for inter-process | |
| 149 // guarded access to data. | |
| 150 class LLock : public Lockable { | |
| 151 public: | |
| 152 LLock(); | |
| 153 virtual ~LLock(); | |
| 154 virtual bool Lock() const; | |
| 155 virtual bool Lock(DWORD wait_ms) const; | |
| 156 virtual bool Unlock() const; | |
| 157 | |
| 158 // Returns the thread id of the owner or 0 if the lock is not owned. | |
| 159 DWORD GetOwner() const; | |
| 160 private: | |
| 161 mutable CRITICAL_SECTION critical_section_; | |
| 162 DISALLOW_EVIL_CONSTRUCTORS(LLock); | |
| 163 }; | |
| 164 | |
| 165 // A gate is a synchronization object used to either stop all | |
| 166 // threads from proceeding through a point or to allow them all to proceed. | |
| 167 class Gate { | |
| 168 public: | |
| 169 // In process gate. | |
| 170 Gate(); | |
| 171 | |
| 172 // Interprocess gate. | |
| 173 explicit Gate(const TCHAR * event_name); | |
| 174 | |
| 175 ~Gate(); | |
| 176 | |
| 177 // Open the gate. | |
| 178 bool Open(); | |
| 179 | |
| 180 // Close the gate. | |
| 181 bool Close(); | |
| 182 | |
| 183 // Wait to enter the gate. | |
| 184 bool Wait(DWORD msec); | |
| 185 | |
| 186 // Conversion from the object to a HANDLE. | |
| 187 operator HANDLE() const {return gate_;} | |
| 188 | |
| 189 // Returns S_OK, and sets selected_gate to zero based index of the gate that | |
| 190 // was opened. | |
| 191 // Returns E_FAIL if timeout occured or gate was abandoned. | |
| 192 static HRESULT WaitAny(Gate const * const *gates, | |
| 193 int num_gates, | |
| 194 DWORD msec, | |
| 195 int *selected_gate); | |
| 196 | |
| 197 // Returns S_OK if all gates were opened | |
| 198 // Returns E_FAIL if timeout occured or gate was abandoned. | |
| 199 static HRESULT WaitAll(Gate const * const *gates, int num_gates, DWORD msec); | |
| 200 | |
| 201 private: | |
| 202 bool Initialize(const TCHAR * event_name); | |
| 203 static HRESULT WaitMultipleHelper(Gate const * const *gates, | |
| 204 int num_gates, | |
| 205 DWORD msec, | |
| 206 int *selected_gate, | |
| 207 bool wait_all); | |
| 208 HANDLE gate_; | |
| 209 DISALLOW_EVIL_CONSTRUCTORS(Gate); | |
| 210 }; | |
| 211 | |
| 212 bool WaitAllowRepaint(const Gate& gate, DWORD msec); | |
| 213 | |
| 214 class AutoGateKeeper { | |
| 215 public: | |
| 216 explicit AutoGateKeeper(Gate *gate) : gate_(gate) { | |
| 217 gate_->Open(); | |
| 218 } | |
| 219 ~AutoGateKeeper() { | |
| 220 gate_->Close(); | |
| 221 } | |
| 222 private: | |
| 223 Gate *gate_; | |
| 224 DISALLOW_EVIL_CONSTRUCTORS(AutoGateKeeper); | |
| 225 }; | |
| 226 | |
| 227 // A very simple rather fast lock - if uncontested. USE ONLY AS A GLOBAL OBJECT | |
| 228 // (i.e., DECLARED AT FILE SCOPE or as a STATIC CLASS MEMBER) - this is not | |
| 229 // enforced. Uses interlocked instructions on an int to get a fast user-mode | |
| 230 // lock. (Locks the bus and does a couple of memory references so it isn't | |
| 231 // free.) Spin-waits to get the lock. Has the advantage that it needs no | |
| 232 // initialization - thus has no order-of-evaluation problems with respect to | |
| 233 // other global objects. Does not work (causes deadlock) if locked twice by | |
| 234 // the same thread. (Has no constructor so is initialized to 0 by C++. | |
| 235 // This is why it must be a global or static class member: it doesn't initialize | |
| 236 // itself to 0. This is also why it doesn't inherit from Lockable, which would | |
| 237 // make it need to initialize a virtual table.) | |
| 238 struct SimpleLock { | |
| 239 bool Lock() const; | |
| 240 bool Unlock() const; | |
| 241 private: | |
| 242 mutable volatile long lock_; | |
| 243 }; | |
| 244 | |
| 245 struct SimpleLockWithDelay { | |
| 246 bool Lock() const; | |
| 247 bool Unlock() const; | |
| 248 private: | |
| 249 mutable volatile long lock_; | |
| 250 }; | |
| 251 | |
| 252 class AutoSimpleLock { | |
| 253 public: | |
| 254 explicit AutoSimpleLock(const SimpleLock& lock) | |
| 255 : lock_(lock) { lock_.Lock(); } | |
| 256 ~AutoSimpleLock() { lock_.Unlock(); } | |
| 257 private: | |
| 258 const SimpleLock& lock_; | |
| 259 DISALLOW_EVIL_CONSTRUCTORS(AutoSimpleLock); | |
| 260 }; | |
| 261 | |
| 262 class AutoSimpleLockWithDelay { | |
| 263 public: | |
| 264 explicit AutoSimpleLockWithDelay(const SimpleLockWithDelay& lock) | |
| 265 : lock_(lock) { lock_.Lock(); } | |
| 266 ~AutoSimpleLockWithDelay() { lock_.Unlock(); } | |
| 267 private: | |
| 268 const SimpleLockWithDelay& lock_; | |
| 269 DISALLOW_EVIL_CONSTRUCTORS(AutoSimpleLockWithDelay); | |
| 270 }; | |
| 271 | |
| 272 | |
| 273 // allow only one thread to hold a lock | |
| 274 class CriticalSection { | |
| 275 public: | |
| 276 CriticalSection(); | |
| 277 ~CriticalSection(); | |
| 278 | |
| 279 void Enter(); | |
| 280 void Exit(); | |
| 281 | |
| 282 private: | |
| 283 CRITICAL_SECTION critical_section_; | |
| 284 uint32 number_entries_; | |
| 285 | |
| 286 DISALLOW_EVIL_CONSTRUCTORS(CriticalSection); | |
| 287 }; | |
| 288 | |
| 289 // A class that manages a CriticalSection with its lifetime, you pass | |
| 290 // it one in the constructor and then it will either be freed in the | |
| 291 // destructor or implicitly [but only once] | |
| 292 class SingleLock { | |
| 293 public: | |
| 294 // TODO(omaha): Not sure if immediately locking is a good idea; | |
| 295 // the API is asymmetrical (there's an Unlock but no Lock). | |
| 296 | |
| 297 // Lock a critical section immediately | |
| 298 explicit SingleLock(CriticalSection * cs); | |
| 299 | |
| 300 // If we have not explicitly unlocked it, this destructor will | |
| 301 ~SingleLock(); | |
| 302 | |
| 303 // Release the lock explicitly [should be called only once, after that | |
| 304 // does nothing. If we do not do so, the destructor will] | |
| 305 HRESULT Unlock(); | |
| 306 | |
| 307 private: | |
| 308 CriticalSection * critical_section_; | |
| 309 | |
| 310 DISALLOW_EVIL_CONSTRUCTORS(SingleLock); | |
| 311 }; | |
| 312 | |
| 313 // Encapsulation for kernel Event. Initializes and destroys with it's lifetime | |
| 314 class EventObj { | |
| 315 public: | |
| 316 explicit EventObj(const TCHAR * event_name) { | |
| 317 Init(event_name); | |
| 318 } | |
| 319 ~EventObj(); | |
| 320 void Init(const TCHAR * event_name); | |
| 321 BOOL SetEvent(); | |
| 322 HANDLE GetHandle() { return h_; } | |
| 323 | |
| 324 private: | |
| 325 HANDLE h_; | |
| 326 | |
| 327 DISALLOW_EVIL_CONSTRUCTORS(EventObj); | |
| 328 }; | |
| 329 | |
| 330 // Is the given handle signaled? | |
| 331 // | |
| 332 // Typically used for events. | |
| 333 bool IsHandleSignaled(HANDLE h); | |
| 334 | |
| 335 | |
| 336 enum SyncScope { | |
| 337 // local to a session | |
| 338 SYNC_LOCAL, | |
| 339 | |
| 340 // global scope but the name is decorated to make it unique for the user | |
| 341 SYNC_USER, | |
| 342 | |
| 343 // a globally scoped name | |
| 344 SYNC_GLOBAL, | |
| 345 }; | |
| 346 | |
| 347 // Create an id for the events/mutexes that can be used at the given scope | |
| 348 void CreateSyncId(const TCHAR* id, SyncScope scope, CString* sync_id); | |
| 349 | |
| 350 // If any place needs to create a mutex that multiple | |
| 351 // processes need to access, use this. | |
| 352 HANDLE CreateMutexWithSyncAccess(const TCHAR* name, | |
| 353 LPSECURITY_ATTRIBUTES lock_attributes); | |
| 354 | |
| 355 } // namespace omaha | |
| 356 | |
| 357 #endif // OMAHA_BASE_SYNCHRONIZED_H_ | |
| 358 | |
| OLD | NEW |