You've already forked linux-packaging-mono
Imported Upstream version 5.12.0.220
Former-commit-id: c477e03582759447177c6d4bf412cd2355aad476
This commit is contained in:
parent
8bd104cef2
commit
8fc30896db
@ -47,12 +47,68 @@ namespace System.Threading
|
||||
|
||||
internal const int MaxWaitHandles = 64;
|
||||
|
||||
// We rely on the reference source implementation of WaitHandle, and it delegates to a function named
|
||||
// WaitOneNative to perform the actual operation of waiting on a handle.
|
||||
// This native operation actually has to call back into managed code and invoke .Wait
|
||||
// on the current SynchronizationContext. As such, our implementation of this "native" method
|
||||
// is actually managed code, and the real native icall being used is Wait_internal.
|
||||
static int WaitOneNative (SafeHandle waitableSafeHandle, uint millisecondsTimeout, bool hasThreadAffinity, bool exitContext)
|
||||
{
|
||||
bool release = false;
|
||||
#if !MONODROID
|
||||
var context = SynchronizationContext.Current;
|
||||
#endif
|
||||
try {
|
||||
waitableSafeHandle.DangerousAddRef (ref release);
|
||||
|
||||
#if !DISABLE_REMOTING
|
||||
if (exitContext)
|
||||
SynchronizationAttribute.ExitContext ();
|
||||
#endif
|
||||
|
||||
#if !MONODROID
|
||||
// HACK: Documentation (and public posts by experts like Joe Duffy) suggests that
|
||||
// users must first call SetWaitNotificationRequired to flag that a given synchronization
|
||||
// context overrides .Wait. Because invoking the Wait method is somewhat expensive, we use
|
||||
// the notification-required flag to determine whether or not we should invoke the managed
|
||||
// wait method.
|
||||
// Another option would be to check whether this context uses the default Wait implementation,
|
||||
// but I don't know of a cheap way to do this that handles derived types correctly.
|
||||
// If the thread does not have a synchronization context set at all, we can safely just
|
||||
// jump directly to invoking Wait_internal.
|
||||
if ((context != null) && context.IsWaitNotificationRequired ()) {
|
||||
return context.Wait (
|
||||
new IntPtr[] { waitableSafeHandle.DangerousGetHandle () },
|
||||
false,
|
||||
(int)millisecondsTimeout
|
||||
);
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
unsafe {
|
||||
IntPtr handle = waitableSafeHandle.DangerousGetHandle ();
|
||||
return Wait_internal (&handle, 1, false, (int)millisecondsTimeout);
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
if (release)
|
||||
waitableSafeHandle.DangerousRelease ();
|
||||
|
||||
#if !DISABLE_REMOTING
|
||||
if (exitContext)
|
||||
SynchronizationAttribute.EnterContext ();
|
||||
#endif
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static int WaitMultiple(WaitHandle[] waitHandles, int millisecondsTimeout, bool exitContext, bool WaitAll)
|
||||
{
|
||||
if (waitHandles.Length > MaxWaitHandles)
|
||||
return WAIT_FAILED;
|
||||
|
||||
int release_last = -1;
|
||||
var context = SynchronizationContext.Current;
|
||||
|
||||
try {
|
||||
#if !DISABLE_REMOTING
|
||||
@ -70,45 +126,31 @@ namespace System.Threading
|
||||
}
|
||||
}
|
||||
|
||||
unsafe {
|
||||
IntPtr* handles = stackalloc IntPtr[waitHandles.Length];
|
||||
|
||||
if ((context != null) && context.IsWaitNotificationRequired ()) {
|
||||
IntPtr[] handles = new IntPtr[waitHandles.Length];
|
||||
for (int i = 0; i < waitHandles.Length; ++i)
|
||||
handles[i] = waitHandles[i].SafeWaitHandle.DangerousGetHandle ();
|
||||
|
||||
return Wait_internal(handles, waitHandles.Length, WaitAll, millisecondsTimeout);
|
||||
return context.Wait (
|
||||
handles,
|
||||
false,
|
||||
(int)millisecondsTimeout
|
||||
);
|
||||
} else {
|
||||
unsafe {
|
||||
IntPtr* handles = stackalloc IntPtr[waitHandles.Length];
|
||||
|
||||
for (int i = 0; i < waitHandles.Length; ++i)
|
||||
handles[i] = waitHandles[i].SafeWaitHandle.DangerousGetHandle ();
|
||||
|
||||
return Wait_internal (handles, waitHandles.Length, WaitAll, millisecondsTimeout);
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
for (int i = release_last; i >= 0; --i) {
|
||||
waitHandles [i].SafeWaitHandle.DangerousRelease ();
|
||||
}
|
||||
|
||||
#if !DISABLE_REMOTING
|
||||
if (exitContext)
|
||||
SynchronizationAttribute.EnterContext ();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
static int WaitOneNative (SafeHandle waitableSafeHandle, uint millisecondsTimeout, bool hasThreadAffinity, bool exitContext)
|
||||
{
|
||||
bool release = false;
|
||||
try {
|
||||
#if !DISABLE_REMOTING
|
||||
if (exitContext)
|
||||
SynchronizationAttribute.ExitContext ();
|
||||
#endif
|
||||
|
||||
waitableSafeHandle.DangerousAddRef (ref release);
|
||||
|
||||
unsafe {
|
||||
IntPtr handle = waitableSafeHandle.DangerousGetHandle();
|
||||
return Wait_internal(&handle, 1, false, (int)millisecondsTimeout);
|
||||
}
|
||||
} finally {
|
||||
if (release)
|
||||
waitableSafeHandle.DangerousRelease ();
|
||||
|
||||
#if !DISABLE_REMOTING
|
||||
if (exitContext)
|
||||
SynchronizationAttribute.EnterContext ();
|
||||
@ -117,7 +159,7 @@ namespace System.Threading
|
||||
}
|
||||
|
||||
[MethodImplAttribute(MethodImplOptions.InternalCall)]
|
||||
unsafe static extern int Wait_internal(IntPtr* handles, int numHandles, bool waitAll, int ms);
|
||||
internal unsafe static extern int Wait_internal(IntPtr* handles, int numHandles, bool waitAll, int ms);
|
||||
|
||||
static int SignalAndWaitOne (SafeWaitHandle waitHandleToSignal,SafeWaitHandle waitHandleToWaitOn, int millisecondsTimeout, bool hasThreadAffinity, bool exitContext)
|
||||
{
|
||||
|
Reference in New Issue
Block a user