1 /***
2 *lock.h
3 *
4 *           Copyright (c) Microsoft Corporation. All rights reserved.
5 *
6 *Purpose:     lock class for automatically acquiring/releasing
7 *                  the monitor lock on managed types.
8 *
9 *           [Public]
10 *
11 ****/
12
13 #pragma once
14
15 #if !defined(_INC_MSCLR_LOCK)
16
17 #ifndef __cplusplus_cli
18 #error ERROR: msclr libraries are not compatible with /clr:oldSyntax
19 #endif
20
21 #using <mscorlib.dll>
22 #include <msclr\safebool.h>
23 #if !defined(_M_CEE_SAFE)
24 #include <vcclr.h>
25 #endif
26
27 namespace msclr
28 {
29
30       // The lock_when enumeration is used to defer the lock object
31       // from taking the lock.
32       enum lock_when { lock_later };
33
34       ref class lock
35       {
36       private:
37              System::Object ^ m_object;
38              bool                     m_locked;
39
40              template<class T,class U> value struct is_not { typedef int __dont_use_this_type__; };
41              template<class T> value struct is_not<T,T> { };
42
43       public:
44              // By default, take the lock immediately with an infinite timeout.
45              // Accept an optional timespan (in milliseconds) and throw on failure or timeout.
46              template<class T> lock( T ^ _object) 
47                     : m_object( _object ),
48                        m_locked( false )
49              {
50                     // ensure that T is not a ReaderWriterLock.
51                     is_not<T, System::Threading::ReaderWriterLock>::__dont_use_this_type__ _Diagnostic;
52                     (_Diagnostic);
53
54                     acquire(System::Threading::Timeout::Infinite);
55              }
56
57              template<class T> lock( T ^ _object, int _timeout )
58                     : m_object( _object ),
59                        m_locked( false )
60              {
61                     // ensure that T is not a ReaderWriterLock.
62                     is_not<T, System::Threading::ReaderWriterLock>::__dont_use_this_type__ _Diagnostic;
63                     (_Diagnostic);
64
65                     acquire( _timeout );
66              }
67
68              // By default, take the lock immediately within the specified timespan 
69              // and throw on failure or timeout.
70              template<class T> lock( T ^ _object, System::TimeSpan _timeout )
71                     : m_object( _object ),
72                        m_locked( false )
73              {
74                     // ensure that T is not a ReaderWriterLock.
75                     is_not<T, System::Threading::ReaderWriterLock>::__dont_use_this_type__ _Diagnostic;
76                     (_Diagnostic);
77
78                     acquire( _timeout );
79              }
80
81              // If you use the "lock_later" enumeration, it causes lock
82              // to defer taking the lock.
83              template<class T> lock( T ^ _object, lock_when )
84                     : m_object( _object ),
85                        m_locked( false )
86              {
87                     // ensure that T is not a ReaderWriterLock.
88                     is_not<T, System::Threading::ReaderWriterLock>::__dont_use_this_type__ _Diagnostic;
89                     (_Diagnostic);
90              }
91
92 #if !defined(_M_CEE_SAFE)
93              template<class T> lock( gcroot<T ^> _object) 
94                     : m_object( _object ),
95                        m_locked( false )
96              {
97                     // ensure that T is not a ReaderWriterLock.
98                     is_not<T, System::Threading::ReaderWriterLock>::__dont_use_this_type__ _Diagnostic;
99                     (_Diagnostic);
100
101                     acquire(System::Threading::Timeout::Infinite);
102              }
103
104
105              template<class T> lock( gcroot<T ^> _object, int _timeout )
106                     : m_object( _object ),
107                        m_locked( false )
108              {
109                     // ensure that T is not a ReaderWriterLock.
110                     is_not<T, System::Threading::ReaderWriterLock>::__dont_use_this_type__ _Diagnostic;
111                     (_Diagnostic);
112
113                     acquire( _timeout );
114              }
115
116              // By default, take the lock immediately within the specified timespan 
117              // and throw on failure or timeout.
118              template<class T> lock( gcroot<T ^> _object, System::TimeSpan _timeout )
119                     : m_object( _object ),
120                        m_locked( false )
121              {
122                     // ensure that T is not a ReaderWriterLock.
123                     is_not<T, System::Threading::ReaderWriterLock>::__dont_use_this_type__ _Diagnostic;
124                     (_Diagnostic);
125
126                     acquire( _timeout );
127              }
128
129              // If you use the "lock_later" enumeration, it causes lock
130              // to defer taking the lock.
131              template<class T> lock( gcroot<T ^> _object, lock_when )
132                     : m_object( _object ),
133                        m_locked( false )
134              {
135                     // ensure that T is not a ReaderWriterLock.
136                     is_not<T, System::Threading::ReaderWriterLock>::__dont_use_this_type__ _Diagnostic;
137                     (_Diagnostic);
138              }
139 #endif /* if !defined(_M_CEE_SAFE) */
140
141              // release the lock if it is not currently held
142              ~lock()
143              {
144                     release();
145              }
146
147              // Check to see if this lock object is currently holding the lock
148              bool is_locked()
149              {
150                     return m_locked;
151              }
152
153              // Check to see if this lock object is currently holding the lock
154              operator _detail_class::_safe_bool()
155              {
156                     return is_locked() ? _detail_class::_safe_true : _detail_class::_safe_false;
157              }
158
159              // disallow explicit comparisons to _safe_bool
160              template<class T> bool operator==( T t )
161              {
162                     // ensure that T is not a _safe_bool.
163                     is_not<T, _detail_class::_safe_bool>::__dont_use_this_type__ _Diagnostic;
164                     (_Diagnostic);
165
166                     return m_object == t;
167              }
168
169              template<class T> bool operator!=( T t )
170              {
171                     // ensure that T is not a _safe_bool.
Lines 172 ... 181 are skipped.
182                     if( ! m_locked )
183                     {
184                           if( ! System::Threading::Monitor::TryEnter( m_object, _timeout ) )
185                           {
186                                  throw gcnew System::ApplicationException( "lock timeout" );
187                           }
188                           m_locked = true;
189                     }
190              }
191
192              void acquire()
193              {
194                     if( ! m_locked )
195                     {
196                           if( ! System::Threading::Monitor::TryEnter( m_object, 
197                                            System::Threading::Timeout::Infinite ) )
198                           {
199                                  throw gcnew System::ApplicationException( "lock timeout" );
200                           }
201                           m_locked = true;
202                     }
203              }
204
205              // Take the lock within the specified timespan. 
206              // Throw an ApplicationException on timeout.
207              void acquire( System::TimeSpan _timeout )
208              {
209                     if( ! m_locked )
210                     {
211                           if( ! System::Threading::Monitor::TryEnter( m_object, _timeout ) )
212                           {
213                                  throw gcnew System::ApplicationException( "lock timeout" );
214                           }
215                           m_locked = true;
216                     }
217              }
218
219              // Try to take the lock within the specified timespan. In the case
220              // of timeout, return false.
221              bool try_acquire( int _timeout ) // throw()
222              {
223                     if( ! m_locked )
224                     {
225                           if( ! System::Threading::Monitor::TryEnter( m_object, _timeout ) )
226                           {
227                                  return false;
228                           }
229                           m_locked = true;
230                     }
231                     return true;
232              }
233
234              // Try to take the lock within the specified timespan. In the case
235              // of timeout, return false.
236              bool try_acquire( System::TimeSpan _timeout ) // throw()
237              {
238                     if( ! m_locked )
239                     {
240                           if( ! System::Threading::Monitor::TryEnter( m_object, _timeout ) )
241                           {
242                                  return false;
243                           }
244                           m_locked = true;
245                     }
246                     return true;
247              }
248
249              // Release the lock if it is currently held
250              void release()
251              {
252                     if( m_locked )
253                     {
254                           m_locked = false;
255                           System::Threading::Monitor::Exit( m_object );
256                     }
257              }
258       };
259 }
260
261 #define _INC_MSCLR_LOCK
262
263 #endif // _INC_MSCLR_LOCK
264