2004-04-01 Martin Baulig <martin@ximian.com>
[mono.git] / mcs / class / corlib / System.Threading / Monitor.cs
1 //
2 // System.Threading.Monitor.cs
3 //
4 // Author:
5 //   Dick Porter (dick@ximian.com)
6 //
7 // (C) Ximian, Inc.  http://www.ximian.com
8 //
9
10 using System.Runtime.CompilerServices;
11
12 namespace System.Threading
13 {
14         public sealed class Monitor
15         {
16                 private Monitor () {}
17
18                 // Grabs the mutex on object 'obj', with a maximum
19                 // wait time 'ms' but doesn't block - if it can't get
20                 // the lock it returns false, true if it can
21                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
22                 private extern static bool Monitor_try_enter(object obj, int ms);
23                 public static void Enter(object obj) {
24                         if(obj==null) {
25                                 throw new ArgumentNullException("Object is null");
26                         }
27                         //if(obj.GetType().IsValueType==true) {
28                         //      throw new ArgumentException("Value type");
29                         //}
30
31                         Monitor_try_enter(obj, Timeout.Infinite);
32                 }
33
34                 // Releases the mutex on object 'obj'
35                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
36                 private extern static void Monitor_exit(object obj);
37
38                 public static void Exit(object obj) {
39                         if(obj==null) {
40                                 throw new ArgumentNullException("Object is null");
41                         }
42                         //if(obj.GetType().IsValueType==true) {
43                         //      throw new ArgumentException("Value type");
44                         //}
45
46                         Monitor_exit(obj);
47                 }
48
49                 // Signals one of potentially many objects waiting on
50                 // object 'obj'
51                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
52                 private extern static void Monitor_pulse(object obj);
53
54                 // Checks whether object 'obj' is currently synchronised
55                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
56                 private extern static bool Monitor_test_synchronised(object obj);
57
58                 public static void Pulse(object obj) {
59                         if(obj==null) {
60                                 throw new ArgumentNullException("Object is null");
61                         }
62                         if(Monitor_test_synchronised(obj)==false) {
63                                 throw new SynchronizationLockException("Object is not synchronized");
64                         }
65
66                         Monitor_pulse(obj);
67                 }
68
69                 // Signals all of potentially many objects waiting on
70                 // object 'obj'
71                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
72                 private extern static void Monitor_pulse_all(object obj);
73
74                 public static void PulseAll(object obj) {
75                         if(obj==null) {
76                                 throw new ArgumentNullException("Object is null");
77                         }
78                         if(Monitor_test_synchronised(obj)==false) {
79                                 throw new SynchronizationLockException("Object is not synchronized");
80                         }
81
82                         Monitor_pulse_all(obj);
83                 }
84
85                 public static bool TryEnter(object obj) {
86                         if(obj==null) {
87                                 throw new ArgumentNullException("Object is null");
88                         }
89                         //if(obj.GetType().IsValueType==true) {
90                         //      throw new ArgumentException("Value type");
91                         //}
92                         
93                         return(Monitor_try_enter(obj, 0));
94                 }
95
96                 public static bool TryEnter(object obj, int millisecondsTimeout) {
97                         if(obj==null) {
98                                 throw new ArgumentNullException("Object is null");
99                         }
100                         //if(obj.GetType().IsValueType==true) {
101                         //      throw new ArgumentException("Value type");
102                         //}
103
104                         // LAMESPEC: should throw an exception when ms<0, but
105                         // Timeout.Infinite is -1
106                         if(millisecondsTimeout == Timeout.Infinite) {
107                                 Enter(obj);
108                                 return(true);
109                         }
110                         
111                         if(millisecondsTimeout<0) {
112                                 throw new ArgumentException("millisecondsTimeout negative");
113                         }
114                         
115                         return(Monitor_try_enter(obj, millisecondsTimeout));
116                 }
117
118                 public static bool TryEnter(object obj, TimeSpan timeout) {
119                         if(obj==null) {
120                                 throw new ArgumentNullException("Object is null");
121                         }
122                         //if(obj.GetType().IsValueType==true) {
123                         //      throw new ArgumentException("Value type");
124                         //}
125
126                         // LAMESPEC: should throw an exception when ms<0, but
127                         // Timeout.Infinite is -1
128                         int ms=Convert.ToInt32(timeout.TotalMilliseconds);
129                         
130                         if(ms == Timeout.Infinite) {
131                                 Enter(obj);
132                                 return(true);
133                         }
134
135                         if(ms < 0 || ms > Int32.MaxValue) {
136                                 throw new ArgumentOutOfRangeException("timeout out of range");
137                         }
138                         
139                         return(Monitor_try_enter(obj, ms));
140                 }
141
142                 // Waits for a signal on object 'obj' with maximum
143                 // wait time 'ms'. Returns true if the object was
144                 // signalled, false if it timed out
145                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
146                 private extern static bool Monitor_wait(object obj, int ms);
147
148                 public static bool Wait(object obj) {
149                         if(obj==null) {
150                                 throw new ArgumentNullException("Object is null");
151                         }
152                         if(Monitor_test_synchronised(obj)==false) {
153                                 throw new SynchronizationLockException("Object is not synchronized");
154                         }
155
156                         return(Monitor_wait(obj, Timeout.Infinite));
157                 }
158
159                 public static bool Wait(object obj, int millisecondsTimeout) {
160                         if(obj==null) {
161                                 throw new ArgumentNullException("Object is null");
162                         }
163                         if(Monitor_test_synchronised(obj)==false) {
164                                 throw new SynchronizationLockException("Object is not synchronized");
165                         }
166                         // LAMESPEC: no mention of timeout sanity checking
167
168                         return(Monitor_wait(obj, millisecondsTimeout));
169                 }
170
171                 public static bool Wait(object obj, TimeSpan timeout) {
172                         if(obj==null) {
173                                 throw new ArgumentNullException("Object is null");
174                         }
175                         // LAMESPEC: says to throw ArgumentException too
176                         int ms=Convert.ToInt32(timeout.TotalMilliseconds);
177                         
178                         if(ms < 0 || ms > Int32.MaxValue) {
179                                 throw new ArgumentOutOfRangeException("timeout out of range");
180                         }
181                         if(Monitor_test_synchronised(obj)==false) {
182                                 throw new SynchronizationLockException("Object is not synchronized");
183                         }
184
185                         return(Monitor_wait(obj, ms));
186                 }
187
188                 [MonoTODO]
189                 public static bool Wait(object obj, int millisecondsTimeout, bool exitContext) {
190                         if(obj==null) {
191                                 throw new ArgumentNullException("Object is null");
192                         }
193                         // FIXME when I understand what a
194                         // "synchronisation domain" is and does
195                         return(false);
196                 }
197
198                 [MonoTODO]
199                 public static bool Wait(object obj, TimeSpan timeout, bool exitContext) {
200                         if(obj==null) {
201                                 throw new ArgumentNullException("Object is null");
202                         }
203                         // LAMESPEC: says to throw ArgumentException too
204                         int ms=Convert.ToInt32(timeout.TotalMilliseconds);
205                         
206                         if(ms < 0 || ms > Int32.MaxValue) {
207                                 throw new ArgumentOutOfRangeException("timeout out of range");
208                         }
209                         
210                         // FIXME when I understand what a
211                         // "synchronisation domain" is and does
212                         return(false);
213                 }
214         }
215 }