Updates referencesource to .NET 4.7
[mono-project.git] / mcs / class / referencesource / mscorlib / system / threading / monitor.cs
blobfbf264dad25770f6b3a849b51e1ad0359ea2a027
1 // ==++==
2 //
3 // Copyright (c) Microsoft Corporation. All rights reserved.
4 //
5 // ==--==
6 //
7 // <OWNER>Microsoft</OWNER>
8 /*=============================================================================
9 **
10 ** Class: Monitor
13 ** Purpose: Synchronizes access to a shared resource or region of code in a multi-threaded
14 ** program.
17 =============================================================================*/
20 namespace System.Threading {
22 using System;
23 using System.Security.Permissions;
24 using System.Runtime;
25 using System.Runtime.Remoting;
26 using System.Threading;
27 using System.Runtime.CompilerServices;
28 using System.Runtime.ConstrainedExecution;
29 using System.Runtime.Versioning;
30 using System.Diagnostics.Contracts;
32 [HostProtection(Synchronization=true, ExternalThreading=true)]
33 [System.Runtime.InteropServices.ComVisible(true)]
34 public static partial class Monitor
36 /*=========================================================================
37 ** Obtain the monitor lock of obj. Will block if another thread holds the lock
38 ** Will not block if the current thread holds the lock,
39 ** however the caller must ensure that the same number of Exit
40 ** calls are made as there were Enter calls.
42 ** Exceptions: ArgumentNullException if object is null.
43 =========================================================================*/
44 [System.Security.SecuritySafeCritical]
45 [ResourceExposure(ResourceScope.None)]
46 [MethodImplAttribute(MethodImplOptions.InternalCall)]
47 public static extern void Enter(Object obj);
50 // Use a ref bool instead of out to ensure that unverifiable code must
51 // initialize this value to something. If we used out, the value
52 // could be uninitialized if we threw an exception in our prolog.
53 // The JIT should inline this method to allow check of lockTaken argument to be optimized out
54 // in the typical case. Note that the method has to be transparent for inlining to be allowed by the VM.
55 public static void Enter(Object obj, ref bool lockTaken)
57 if (lockTaken)
58 ThrowLockTakenException();
60 ReliableEnter(obj, ref lockTaken);
61 Contract.Assert(lockTaken);
64 private static void ThrowLockTakenException()
66 throw new ArgumentException(Environment.GetResourceString("Argument_MustBeFalse"), "lockTaken");
69 #if !MONO
70 [System.Security.SecuritySafeCritical]
71 [ResourceExposure(ResourceScope.None)]
72 [MethodImplAttribute(MethodImplOptions.InternalCall)]
73 private static extern void ReliableEnter(Object obj, ref bool lockTaken);
74 #endif
77 /*=========================================================================
78 ** Release the monitor lock. If one or more threads are waiting to acquire the
79 ** lock, and the current thread has executed as many Exits as
80 ** Enters, one of the threads will be unblocked and allowed to proceed.
82 ** Exceptions: ArgumentNullException if object is null.
83 ** SynchronizationLockException if the current thread does not
84 ** own the lock.
85 =========================================================================*/
86 [System.Security.SecuritySafeCritical]
87 [ResourceExposure(ResourceScope.None)]
88 [MethodImplAttribute(MethodImplOptions.InternalCall)]
89 [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
90 public static extern void Exit(Object obj);
92 /*=========================================================================
93 ** Similar to Enter, but will never block. That is, if the current thread can
94 ** acquire the monitor lock without blocking, it will do so and TRUE will
95 ** be returned. Otherwise FALSE will be returned.
97 ** Exceptions: ArgumentNullException if object is null.
98 =========================================================================*/
99 public static bool TryEnter(Object obj)
101 bool lockTaken = false;
102 TryEnter(obj, 0, ref lockTaken);
103 return lockTaken;
106 // The JIT should inline this method to allow check of lockTaken argument to be optimized out
107 // in the typical case. Note that the method has to be transparent for inlining to be allowed by the VM.
108 public static void TryEnter(Object obj, ref bool lockTaken)
110 if (lockTaken)
111 ThrowLockTakenException();
113 ReliableEnterTimeout(obj, 0, ref lockTaken);
116 /*=========================================================================
117 ** Version of TryEnter that will block, but only up to a timeout period
118 ** expressed in milliseconds. If timeout == Timeout.Infinite the method
119 ** becomes equivalent to Enter.
121 ** Exceptions: ArgumentNullException if object is null.
122 ** ArgumentException if timeout < 0.
123 =========================================================================*/
124 // The JIT should inline this method to allow check of lockTaken argument to be optimized out
125 // in the typical case. Note that the method has to be transparent for inlining to be allowed by the VM.
126 public static bool TryEnter(Object obj, int millisecondsTimeout)
128 bool lockTaken = false;
129 TryEnter(obj, millisecondsTimeout, ref lockTaken);
130 return lockTaken;
133 private static int MillisecondsTimeoutFromTimeSpan(TimeSpan timeout)
135 long tm = (long)timeout.TotalMilliseconds;
136 if (tm < -1 || tm > (long)Int32.MaxValue)
137 throw new ArgumentOutOfRangeException("timeout", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegOrNegative1"));
138 return (int)tm;
141 public static bool TryEnter(Object obj, TimeSpan timeout)
143 return TryEnter(obj, MillisecondsTimeoutFromTimeSpan(timeout));
146 // The JIT should inline this method to allow check of lockTaken argument to be optimized out
147 // in the typical case. Note that the method has to be transparent for inlining to be allowed by the VM.
148 public static void TryEnter(Object obj, int millisecondsTimeout, ref bool lockTaken)
150 if (lockTaken)
151 ThrowLockTakenException();
153 ReliableEnterTimeout(obj, millisecondsTimeout, ref lockTaken);
156 public static void TryEnter(Object obj, TimeSpan timeout, ref bool lockTaken)
158 if (lockTaken)
159 ThrowLockTakenException();
161 ReliableEnterTimeout(obj, MillisecondsTimeoutFromTimeSpan(timeout), ref lockTaken);
164 #if !MONO
165 [System.Security.SecuritySafeCritical]
166 [ResourceExposure(ResourceScope.None)]
167 [MethodImplAttribute(MethodImplOptions.InternalCall)]
168 private static extern void ReliableEnterTimeout(Object obj, int timeout, ref bool lockTaken);
169 #endif
171 [System.Security.SecuritySafeCritical]
172 public static bool IsEntered(object obj)
174 if (obj == null)
175 throw new ArgumentNullException("obj");
177 return IsEnteredNative(obj);
180 #if !MONO
181 [System.Security.SecurityCritical]
182 [ResourceExposure(ResourceScope.None)]
183 [MethodImplAttribute(MethodImplOptions.InternalCall)]
184 private static extern bool IsEnteredNative(Object obj);
185 #endif
187 /*========================================================================
188 ** Waits for notification from the object (via a Pulse/PulseAll).
189 ** timeout indicates how long to wait before the method returns.
190 ** This method acquires the monitor waithandle for the object
191 ** If this thread holds the monitor lock for the object, it releases it.
192 ** On exit from the method, it obtains the monitor lock back.
193 ** If exitContext is true then the synchronization domain for the context
194 ** (if in a synchronized context) is exited before the wait and reacquired
196 ** Exceptions: ArgumentNullException if object is null.
197 ========================================================================*/
198 #if !MONO
199 [System.Security.SecurityCritical] // auto-generated
200 [ResourceExposure(ResourceScope.None)]
201 [MethodImplAttribute(MethodImplOptions.InternalCall)]
202 private static extern bool ObjWait(bool exitContext, int millisecondsTimeout, Object obj);
203 #endif
205 [System.Security.SecuritySafeCritical] // auto-generated
206 public static bool Wait(Object obj, int millisecondsTimeout, bool exitContext)
208 if (obj == null)
209 throw (new ArgumentNullException("obj"));
210 return ObjWait(exitContext, millisecondsTimeout, obj);
213 public static bool Wait(Object obj, TimeSpan timeout, bool exitContext)
215 return Wait(obj, MillisecondsTimeoutFromTimeSpan(timeout), exitContext);
218 public static bool Wait(Object obj, int millisecondsTimeout)
220 return Wait(obj, millisecondsTimeout, false);
223 public static bool Wait(Object obj, TimeSpan timeout)
225 return Wait(obj, MillisecondsTimeoutFromTimeSpan(timeout), false);
228 public static bool Wait(Object obj)
230 return Wait(obj, Timeout.Infinite, false);
233 /*========================================================================
234 ** Sends a notification to a single waiting object.
235 * Exceptions: SynchronizationLockException if this method is not called inside
236 * a synchronized block of code.
237 ========================================================================*/
238 #if !MONO
239 [System.Security.SecurityCritical] // auto-generated
240 [ResourceExposure(ResourceScope.None)]
241 [MethodImplAttribute(MethodImplOptions.InternalCall)]
242 private static extern void ObjPulse(Object obj);
243 #endif
245 [System.Security.SecuritySafeCritical] // auto-generated
246 public static void Pulse(Object obj)
248 if (obj == null)
250 throw new ArgumentNullException("obj");
252 Contract.EndContractBlock();
254 ObjPulse(obj);
256 /*========================================================================
257 ** Sends a notification to all waiting objects.
258 ========================================================================*/
259 #if !MONO
260 [System.Security.SecurityCritical] // auto-generated
261 [ResourceExposure(ResourceScope.None)]
262 [MethodImplAttribute(MethodImplOptions.InternalCall)]
263 private static extern void ObjPulseAll(Object obj);
264 #endif
266 [System.Security.SecuritySafeCritical] // auto-generated
267 public static void PulseAll(Object obj)
269 if (obj == null)
271 throw new ArgumentNullException("obj");
273 Contract.EndContractBlock();
275 ObjPulseAll(obj);