3 // Copyright (c) Microsoft Corporation. All rights reserved.
7 // <OWNER>Microsoft</OWNER>
8 /*=============================================================================
13 ** Purpose: Synchronizes access to a shared resource or region of code in a multi-threaded
17 =============================================================================*/
20 namespace System
.Threading
{
23 using System
.Security
.Permissions
;
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
)
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");
70 [System
.Security
.SecuritySafeCritical
]
71 [ResourceExposure(ResourceScope
.None
)]
72 [MethodImplAttribute(MethodImplOptions
.InternalCall
)]
73 private static extern void ReliableEnter(Object obj
, ref bool lockTaken
);
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
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
);
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
)
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
);
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"));
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
)
151 ThrowLockTakenException();
153 ReliableEnterTimeout(obj
, millisecondsTimeout
, ref lockTaken
);
156 public static void TryEnter(Object obj
, TimeSpan timeout
, ref bool lockTaken
)
159 ThrowLockTakenException();
161 ReliableEnterTimeout(obj
, MillisecondsTimeoutFromTimeSpan(timeout
), ref lockTaken
);
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
);
171 [System
.Security
.SecuritySafeCritical
]
172 public static bool IsEntered(object obj
)
175 throw new ArgumentNullException("obj");
177 return IsEnteredNative(obj
);
181 [System
.Security
.SecurityCritical
]
182 [ResourceExposure(ResourceScope
.None
)]
183 [MethodImplAttribute(MethodImplOptions
.InternalCall
)]
184 private static extern bool IsEnteredNative(Object obj
);
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 ========================================================================*/
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
);
205 [System
.Security
.SecuritySafeCritical
] // auto-generated
206 public static bool Wait(Object obj
, int millisecondsTimeout
, bool exitContext
)
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 ========================================================================*/
239 [System
.Security
.SecurityCritical
] // auto-generated
240 [ResourceExposure(ResourceScope
.None
)]
241 [MethodImplAttribute(MethodImplOptions
.InternalCall
)]
242 private static extern void ObjPulse(Object obj
);
245 [System
.Security
.SecuritySafeCritical
] // auto-generated
246 public static void Pulse(Object obj
)
250 throw new ArgumentNullException("obj");
252 Contract
.EndContractBlock();
256 /*========================================================================
257 ** Sends a notification to all waiting objects.
258 ========================================================================*/
260 [System
.Security
.SecurityCritical
] // auto-generated
261 [ResourceExposure(ResourceScope
.None
)]
262 [MethodImplAttribute(MethodImplOptions
.InternalCall
)]
263 private static extern void ObjPulseAll(Object obj
);
266 [System
.Security
.SecuritySafeCritical
] // auto-generated
267 public static void PulseAll(Object obj
)
271 throw new ArgumentNullException("obj");
273 Contract
.EndContractBlock();