singrdk/base/Kernel/System/Threading/WaitHandle.cs

148 lines
5.2 KiB
C#

// ==++==
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// ==--==
namespace System.Threading {
using System;
using System.Threading;
using System.Runtime.CompilerServices;
using System.Collections;
using Microsoft.Singularity;
using Microsoft.Singularity.Io;
using Microsoft.Singularity.Scheduling;
[CLSCompliant(false)]
public enum WaitHandleEvent : ushort
{
WaitDone = 10,
}
//| <include path='docs/doc[@for="WaitHandle"]/*' />
[NoCCtor]
[CLSCompliant(false)]
public abstract class WaitHandle
{
// These two fields should only be accessed with interrupts off.
protected volatile int signaled;
protected volatile Thread owner; // Last thread to be notified by this signal.
protected ThreadQueue queue;
protected int id; // unique ID for this waithandle
private static int idGenerator;
// This field is an array of length 1 containing 'this'.
// It is used to avoid allocation when calling WaitAny from WaitOne.
internal WaitHandle[] singleHandle;
//| <include path='docs/doc[@for="WaitHandle.WaitTimeout"]/*' />
public const int WaitTimeout = -1;
//| <include path='docs/doc[@for="WaitHandle.WaitHandle"]/*' />
protected WaitHandle(int initialState)
{
id = ++idGenerator;
owner = null;
queue = new ThreadQueue(this);
signaled = initialState;
singleHandle = new WaitHandle [1] { this };
}
// Called with dispatch lock held and interrupts off.
[NoHeapAllocation]
protected bool NotifyOne()
{
Kernel.Waypoint(201);
ThreadEntry entry = queue.DequeueHead();
if (entry != null) {
//Kernel.Waypoint(202);
owner = entry.Thread;
Monitoring.Log(Monitoring.Provider.WaitHandle,
(ushort)WaitHandleEvent.WaitDone, 0,
(uint)this.id, (uint)owner.threadIndex,
0, 0, 0);
entry.Thread.WaitDone(entry);
//Kernel.Waypoint(203);
return true;
}
return false;
}
// Called with dispatch lock held and interrupts off.
[NoHeapAllocation]
protected bool NotifyAll()
{
Kernel.Waypoint(204);
bool notified = false;
for (ThreadEntry entry; (entry = queue.DequeueHead()) != null;) {
//Kernel.Waypoint(205);
owner = entry.Thread;
Monitoring.Log(Monitoring.Provider.WaitHandle,
(ushort)WaitHandleEvent.WaitDone, 0,
(uint)this.id, (uint)owner.threadIndex,
0, 0, 0);
entry.Thread.WaitDone(entry);
//Kernel.Waypoint(206);
notified = true;
}
//Kernel.Waypoint(207);
return notified;
}
// Called with interrupts off.
internal abstract bool AcquireOrEnqueue(ThreadEntry entry);
/// Used to return a thread which can make progress on this object.
[NoHeapAllocation]
internal abstract Thread GetBeneficiary();
//| <include path='docs/doc[@for="WaitHandle.WaitOne"]/*' />
public bool WaitOne(TimeSpan timeout)
{
return Thread.CurrentThread.WaitAny(singleHandle, 1, timeout) != WaitTimeout;
}
//| <include path='docs/doc[@for="WaitHandle.WaitOne1"]/*' />
internal bool WaitOne(SchedulerTime stop)
{
return Thread.CurrentThread.WaitAny(singleHandle, 1, stop) != WaitTimeout;
}
//| <include path='docs/doc[@for="WaitHandle.WaitOne2"]/*' />
public bool WaitOne()
{
return WaitOne(SchedulerTime.MaxValue);
}
//| <include path='docs/doc[@for="WaitHandle.WaitAny"]/*' />
public static int WaitAny(WaitHandle[] waitHandles,
TimeSpan timeout)
{
return Thread.CurrentThread.WaitAny(waitHandles, waitHandles.Length, timeout);
}
//| <include path='docs/doc[@for="WaitHandle.WaitAny"]/*' />
public static int WaitAny(WaitHandle[] waitHandles,
SchedulerTime stop)
{
return Thread.CurrentThread.WaitAny(waitHandles, waitHandles.Length, stop);
}
//| <include path='docs/doc[@for="WaitHandle.WaitAny"]/*' />
public static int WaitAny(WaitHandle[] waitHandles,
int waitHandlesCount,
SchedulerTime stop)
{
return Thread.CurrentThread.WaitAny(waitHandles, waitHandlesCount, stop);
}
//| <include path='docs/doc[@for="WaitHandle.WaitAny2"]/*' />
public static int WaitAny(WaitHandle[] waitHandles)
{
return WaitAny(waitHandles, SchedulerTime.MaxValue);
}
}
}