OLD | NEW |
| (Empty) |
1 // Copyright 2003-2009 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 // lock_ptr.h | |
17 // | |
18 // A smart pointer to manage synchronized access to a shared resource. | |
19 // | |
20 // LockPtr provides a simple and concise syntax for accessing a | |
21 // shared resource. The LockPtr is a smart pointer and provides | |
22 // pointer operators -> and *. LockPtr does not have copy semantics and it is | |
23 // not intended to be stored in containers. Instead, instances of LockPtr are | |
24 // usually unamed or short-lived named variables. | |
25 // | |
26 // LockPtr uses an external lock, it acquires the lock in the constructor, and | |
27 // it guarantees the lock is released in the destructor. | |
28 // | |
29 // Since different types of locks have different method names, such as | |
30 // Enter/Exit or Lock/Unlock, etc, LockPtr uses an external customizable policy | |
31 // to bind to different operations. The external policy is a set of template | |
32 // functions that can be specialized for different types of locks, if needed. | |
33 // Think of this policy as an adapter between the lock type and the LockPtr. | |
34 // | |
35 // Usage: let's assume that we have the type below: | |
36 // | |
37 // class X { | |
38 // public: | |
39 // X() : i_(0) {} | |
40 // void f() {} | |
41 // | |
42 // private: | |
43 // int i_; | |
44 // | |
45 // friend int LockPtrTest(int, int); | |
46 // }; | |
47 // | |
48 // We have an instance of this type and an external lock instance to serialize | |
49 // the access to the X instance. | |
50 // | |
51 // Using LockPtr, the code is: | |
52 // | |
53 // X x; | |
54 // LLock local_lock; | |
55 // | |
56 // LockPtr<X>(x, local_lock)->f(); | |
57 // | |
58 // For more example, please see the unit test of the module. | |
59 | |
60 | |
61 | |
62 #ifndef OMAHA_COMMON_LOCK_PTR_H_ | |
63 #define OMAHA_COMMON_LOCK_PTR_H_ | |
64 | |
65 #include "omaha/base/debug.h" | |
66 | |
67 namespace omaha { | |
68 | |
69 template <typename T> | |
70 class LockPtr { | |
71 public: | |
72 template <typename U> | |
73 LockPtr(T& obj, U& lock) | |
74 : pobj_(&obj), | |
75 plock_(&lock), | |
76 punlock_method_(&LockPtr::Unlock<U>) { | |
77 AcquireLock(lock); | |
78 } | |
79 | |
80 ~LockPtr() { | |
81 ASSERT1(punlock_method_); | |
82 (this->*punlock_method_)(); | |
83 } | |
84 | |
85 // Pointer behavior | |
86 T& operator*() { | |
87 ASSERT1(pobj_); | |
88 return *pobj_; | |
89 } | |
90 | |
91 T* operator->() { | |
92 return pobj_; | |
93 } | |
94 | |
95 private: | |
96 // template method to restore the type of the lock and to call the | |
97 // release policy for the lock | |
98 template <class U> | |
99 void Unlock() { | |
100 ASSERT1(plock_); | |
101 U& lock = *(static_cast<U*>(plock_)); | |
102 ReleaseLock(lock); | |
103 } | |
104 | |
105 T* pobj_; // managed shared object | |
106 void* plock_; // type-less lock to control access to pobj_ | |
107 | |
108 void (LockPtr::*punlock_method_)(); // the address of the method to Unlock | |
109 | |
110 DISALLOW_EVIL_CONSTRUCTORS(LockPtr); | |
111 }; | |
112 | |
113 // template functions to define the policy of acquiring and releasing | |
114 // the locks. | |
115 template <class Lock> inline void AcquireLock(Lock& lock) { lock.Lock(); } | |
116 template <class Lock> inline void ReleaseLock(Lock& lock) { lock.Unlock(); } | |
117 | |
118 // specialization of policy for diferent types of locks. | |
119 #include "omaha/base/synchronized.h" | |
120 template <> void inline AcquireLock(CriticalSection& cs) { cs.Enter(); } | |
121 template <> void inline ReleaseLock(CriticalSection& cs) { cs.Exit(); } | |
122 | |
123 // Add more policy specializations below, if needed. | |
124 | |
125 } // namespace omaha | |
126 | |
127 #endif // OMAHA_COMMON_LOCK_PTR_H_ | |
128 | |
OLD | NEW |