Ryujinx/Ryujinx.Horizon/Sdk/OsTypes/OsEvent.cs
gdkchan 08831eecf7
IPC refactor part 3+4: New server HIPC message processor (#4188)
* IPC refactor part 3 + 4: New server HIPC message processor with source generator based serialization

* Make types match on calls to AlignUp/AlignDown

* Formatting

* Address some PR feedback

* Move BitfieldExtensions to Ryujinx.Common.Utilities and consolidate implementations

* Rename Reader/Writer to SpanReader/SpanWriter and move to Ryujinx.Common.Memory

* Implement EventType

* Address more PR feedback

* Log request processing errors since they are not normal

* Rename waitable to multiwait and add missing lock

* PR feedback

* Ac_K PR feedback
2023-01-04 23:15:45 +01:00

131 lines
3.4 KiB
C#

using System;
using System.Collections.Generic;
using System.Threading;
namespace Ryujinx.Horizon.Sdk.OsTypes
{
static partial class Os
{
public static void InitializeEvent(out EventType evnt, bool signaled, EventClearMode clearMode)
{
evnt = new EventType
{
MultiWaitHolders = new LinkedList<MultiWaitHolderBase>(),
Signaled = signaled,
InitiallySignaled = signaled,
ClearMode = clearMode,
State = InitializationState.Initialized,
Lock = new object()
};
}
public static void FinalizeEvent(ref EventType evnt)
{
evnt.State = InitializationState.NotInitialized;
}
public static void WaitEvent(ref EventType evnt)
{
lock (evnt.Lock)
{
ulong currentCounter = evnt.BroadcastCounter;
while (!evnt.Signaled)
{
if (currentCounter != evnt.BroadcastCounter)
{
break;
}
Monitor.Wait(evnt.Lock);
}
if (evnt.ClearMode == EventClearMode.AutoClear)
{
evnt.Signaled = false;
}
}
}
public static bool TryWaitEvent(ref EventType evnt)
{
lock (evnt.Lock)
{
bool signaled = evnt.Signaled;
if (evnt.ClearMode == EventClearMode.AutoClear)
{
evnt.Signaled = false;
}
return signaled;
}
}
public static bool TimedWaitEvent(ref EventType evnt, TimeSpan timeout)
{
lock (evnt.Lock)
{
ulong currentCounter = evnt.BroadcastCounter;
while (!evnt.Signaled)
{
if (currentCounter != evnt.BroadcastCounter)
{
break;
}
bool wasSignaledInTime = Monitor.Wait(evnt.Lock, timeout);
if (!wasSignaledInTime)
{
return false;
}
}
if (evnt.ClearMode == EventClearMode.AutoClear)
{
evnt.Signaled = false;
}
}
return true;
}
public static void SignalEvent(ref EventType evnt)
{
lock (evnt.Lock)
{
if (evnt.Signaled)
{
return;
}
evnt.Signaled = true;
if (evnt.ClearMode == EventClearMode.ManualClear)
{
evnt.BroadcastCounter++;
Monitor.PulseAll(evnt.Lock);
}
else
{
Monitor.Pulse(evnt.Lock);
}
foreach (MultiWaitHolderBase holder in evnt.MultiWaitHolders)
{
holder.GetMultiWait().NotifyAndWakeUpThread(holder);
}
}
}
public static void ClearEvent(ref EventType evnt)
{
lock (evnt.Lock)
{
evnt.Signaled = false;
}
}
}
}