]> rtime.felk.cvut.cz Git - l4.git/blob - kernel/fiasco/src/lib/libk/lock_guard.cpp
update
[l4.git] / kernel / fiasco / src / lib / libk / lock_guard.cpp
1 INTERFACE:
2 #include <type_traits>
3
4 //
5 // Regular lock-guard policy, lock on ctor, unlock/reset in dtor
6 //
7 template< typename LOCK >
8 struct Lock_guard_regular_policy
9 {
10   typedef typename LOCK::Status Status;
11   static Status test_and_set(LOCK *l) { return l->test_and_set(); }
12   static void set(LOCK *l, Status s) { l->set(s); }
13 };
14
15 //
16 // Inverse lock-guard policy, unlock in ctor, lock in dtor
17 // NOTE: this is applicable only to some locks (e.g., the cpu lock)
18 //
19 template<typename LOCK>
20 struct Lock_guard_inverse_policy : private LOCK
21 {
22   typedef typename LOCK::Status Status;
23   static Status test_and_set(LOCK *l) { l->clear(); return LOCK::Locked; }
24   static void set(LOCK *l, Status s) { l->set(s); }
25 };
26
27
28 //
29 // Lock_guard: a guard object using a lock such as helping_lock_t
30 //
31 template<
32   typename LOCK,
33   template< typename L > class POLICY = Lock_guard_regular_policy >
34 class Lock_guard
35 {
36   typedef typename cxx::remove_pointer<typename cxx::remove_reference<LOCK>::type>::type Lock;
37   typedef POLICY<Lock> Policy;
38
39   Lock *_lock;
40   typename Policy::Status _state;
41
42   Lock_guard(Lock_guard &) = delete;
43   Lock_guard &operator = (Lock_guard &) = delete;
44 };
45
46 template< typename LOCK>
47 class Lock_guard_2
48 {
49   LOCK *_l1, *_l2;
50   typename LOCK::Status _state1, _state2;
51 };
52
53 IMPLEMENTATION:
54
55
56 PUBLIC template<typename LOCK, template< typename L > class POLICY>
57 inline
58 Lock_guard<LOCK, POLICY>::Lock_guard()
59   : _lock(0)
60 {}
61
62 PUBLIC template<typename LOCK, template< typename L > class POLICY>
63 inline explicit
64 Lock_guard<LOCK, POLICY>::Lock_guard(Lock *l)
65   : _lock(l)
66 {
67   _state = Policy::test_and_set(_lock);
68 }
69
70 PUBLIC template<typename LOCK, template< typename L > class POLICY>
71 inline
72 Lock_guard<LOCK, POLICY>::Lock_guard(Lock_guard &&l)
73   : _lock(l._lock), _state(l._state)
74 {
75   l.release();
76 }
77
78 PUBLIC template<typename LOCK, template< typename L > class POLICY>
79 inline
80 Lock_guard<LOCK, POLICY>
81 Lock_guard<LOCK, POLICY>::operator = (Lock_guard &&l)
82 {
83   reset();
84   _lock = l._lock;
85   _state = l._state;
86   l.release();
87 }
88
89
90 inline template<typename LOCK>
91 Lock_guard<LOCK> lock_guard(LOCK &lock)
92 { return Lock_guard<LOCK>(&lock); }
93
94 inline template<typename LOCK>
95 Lock_guard<LOCK> lock_guard(LOCK *lock)
96 { return Lock_guard<LOCK>(lock); }
97
98 PUBLIC template<typename LOCK, template< typename L > class POLICY>
99 inline
100 void
101 Lock_guard<LOCK, POLICY>::lock(Lock *l)
102 {
103   _lock = l;
104   _state = Policy::test_and_set(l);
105 }
106
107 PUBLIC template<typename LOCK, template< typename L > class POLICY>
108 inline
109 bool
110 Lock_guard<LOCK, POLICY>::check_and_lock(Lock *l)
111 {
112   _lock = l;
113   _state = Policy::test_and_set(l);
114   return _state != Lock::Invalid;
115 }
116
117 PUBLIC template<typename LOCK, template< typename L > class POLICY>
118 inline
119 bool
120 Lock_guard<LOCK, POLICY>::try_lock(Lock *l)
121 {
122   _state = Policy::test_and_set(l);
123   switch (_state)
124     {
125     case Lock::Locked:
126       return true;
127     case Lock::Not_locked:
128       _lock = l;                        // Was not locked -- unlock.
129       return true;
130     default:
131       return false; // Error case -- lock not existent
132     }
133 }
134
135 PUBLIC template<typename LOCK, template< typename L > class POLICY>
136 inline
137 void
138 Lock_guard<LOCK, POLICY>::release()
139 {
140   _lock = 0;
141 }
142
143 PUBLIC template<typename LOCK, template< typename L > class POLICY>
144 inline
145 void
146 Lock_guard<LOCK, POLICY>::reset()
147 {
148   if (_lock)
149     {
150       Policy::set(_lock, _state);
151       _lock = 0;
152     }
153 }
154
155 PUBLIC template<typename LOCK, template< typename L > class POLICY>
156 inline
157 Lock_guard<LOCK, POLICY>::~Lock_guard()
158 {
159   if (_lock)
160     Policy::set(_lock, _state);
161 }
162
163 PUBLIC template<typename LOCK, template< typename L > class POLICY>
164 inline
165 bool
166 Lock_guard<LOCK, POLICY>::was_set(void)
167 {
168   return _state; //!_lock;
169 }
170
171 PUBLIC template<typename LOCK>
172 inline
173 Lock_guard_2<LOCK>::Lock_guard_2()
174   : _l1(0), _l2(0)
175 {}
176
177 PUBLIC template<typename LOCK>
178 inline
179 Lock_guard_2<LOCK>::Lock_guard_2(LOCK *l1, LOCK *l2)
180   : _l1(l1 < l2 ? l1 : l2), _l2(l1 < l2 ? l2 : l1)
181 {
182   _state1 = _l1->test_and_set();
183   if (_l1 == _l2)
184     _l2 = 0;
185   else
186     _state2 = _l2->test_and_set();
187 }
188
189
190 PUBLIC template<typename LOCK>
191 inline
192 void
193 Lock_guard_2<LOCK>::lock(LOCK *l1, LOCK *l2)
194 {
195   _l1 = l1 < l2 ? l1 : l2;
196   _l2 = l1 < l2 ? l2 : l1;
197   _state1 = _l1->test_and_set();
198   if (_l1 == _l2)
199     _l2 = 0;
200   else 
201     _state2 = _l2->test_and_set();
202 }
203
204 PUBLIC template<typename LOCK>
205 inline
206 bool
207 Lock_guard_2<LOCK>::check_and_lock(LOCK *l1, LOCK *l2)
208 {
209   _l1 = l1 < l2 ? l1 : l2;
210   _l2 = l1 < l2 ? l2 : l1;
211   if ((_state1 = _l1->test_and_set()) == LOCK::Invalid)
212     {
213       _l1 = _l2 = 0;
214       return false;
215     }
216
217   if (_l1 == _l2)
218     _l2 = 0;
219   else if ((_state2 = _l2->test_and_set()) == LOCK::Invalid)
220     {
221       _l2 = 0;
222       return false;
223     }
224
225   return true;
226 }
227
228 PUBLIC template<typename LOCK>
229 inline
230 Lock_guard_2<LOCK>::~Lock_guard_2()
231 {
232   if (_l2)
233     _l2->set(_state2);
234
235   if (_l1)
236     _l1->set(_state1);
237 }