Added Semaphore and Mutex

This commit is contained in:
Simon Lübeß
2021-03-03 18:57:42 +01:00
parent 9d52f77b43
commit 4b032d2c7e
6 changed files with 194 additions and 0 deletions
@@ -0,0 +1,49 @@
#if BF_PLATFORM_WINDOWS
using static System.Windows;
namespace GlitchyEngine.Threading
{
extension Mutex
{
internal Handle nativeHandle;
public this(bool initialyOwned = false)
{
nativeHandle = CreateMutexW(null, initialyOwned, null);
Log.EngineLogger.AssertDebug(nativeHandle != 0, scope $"Failed to create mutex. Error code: {GetLastError()}");
}
public ~this()
{
CloseHandle(nativeHandle);
}
public override LockResult Lock(uint32 timeout = InfiniteTimeout)
{
int i = WaitForSingleObject(nativeHandle, timeout);
switch(i)
{
case 0x00000000L:
return .Released;
case 0x00000080L:
return .Abandoned;
case 0x00000102L:
return .Timeout;
case 0xFFFFFFFF:
return .Failed;
default:
return .Unknown;
}
}
public bool Unlock()
{
return ReleaseMutex(nativeHandle);
}
}
}
#endif
@@ -0,0 +1,55 @@
#if BF_PLATFORM_WINDOWS
using static System.Windows;
namespace GlitchyEngine.Threading
{
extension Semaphore
{
internal Handle nativeHandle;
public override this(int32 initialCount = 1, int32 maximumCount = 1)
{
nativeHandle = (.)CreateSemaphoreW(null, initialCount, maximumCount, null);
Log.EngineLogger.AssertDebug(nativeHandle != 0, scope $"Failed to create semaphore. Error code: {GetLastError()}");
}
public ~this()
{
CloseHandle(nativeHandle);
}
public override LockResult Lock(uint32 timeout = InfiniteTimeout)
{
int i = WaitForSingleObject(nativeHandle, timeout);
switch(i)
{
case 0x00000000L:
return .Released;
case 0x00000080L:
return .Abandoned;
case 0x00000102L:
return .Timeout;
case 0xFFFFFFFF:
return .Failed;
default:
return .Unknown;
}
}
public bool Unlock(int32 releaseCount = 1)
{
return ReleaseSemaphore(nativeHandle, releaseCount, null);
}
public bool Unlock(out int32 previousCount, int32 releaseCount = 1)
{
previousCount = ?;
return ReleaseSemaphore(nativeHandle, releaseCount, &previousCount);
}
}
}
#endif
@@ -0,0 +1,38 @@
namespace System
{
extension Windows
{
public struct SecurityAttributes
{
public uint32 Length;
public SECURITY_DESCRIPTOR* SecurityDescriptor;
public IntBool InheritHandle;
}
[LinkName(.C)]
public static extern Windows.Handle CreateSemaphoreW(SecurityAttributes* semaphoreAttributes, int32 initialCount, int32 maximumCount, char16* name);
[LinkName(.C)]
public static extern uint32 WaitForSingleObject(Handle handle, uint32 timeout);
[LinkName(.C)]
public static extern uint32 WaitForMultipleObjects(uint32 count, Handle *handles, IntBool bWaitAll, uint32 timeout);
public const uint32 InfiniteTimeout = 0xFFFFFFFF;
[Inline]
public static uint32 WaitForMultipleObjects(Handle[] handles, bool waitForAll, uint32 timeout = InfiniteTimeout)
{
return WaitForMultipleObjects((.)handles.Count, handles.CArray(), waitForAll, timeout);
}
[LinkName(.C)]
public static extern IntBool ReleaseSemaphore(Handle semaphore, int32 releaseCount, int32* previousCount);
[LinkName(.C)]
public static extern Handle CreateMutexW(SecurityAttributes* mutexAttributes, IntBool initialOwner, char16* name);
[LinkName(.C)]
public static extern IntBool ReleaseMutex(Handle mutex);
}
}
+24
View File
@@ -0,0 +1,24 @@
namespace GlitchyEngine.Threading
{
public enum LockResult
{
/**
* The lock was released by the owning thread.
*/
Released,
/**
* The owning thread terminated without releasing the lock.
*/
Abandoned,
/**
* The lock function timed out.
*/
Timeout,
/**
* The function has failed.
*/
Failed,
Unknown
}
}
+13
View File
@@ -0,0 +1,13 @@
namespace GlitchyEngine.Threading
{
public class Mutex
{
public extern this(bool initialyOwned = false);
public const uint32 InfiniteTimeout = 0xFFFFFFFF;
public extern LockResult Lock(uint32 timeout = InfiniteTimeout);
public extern bool Unlock();
}
}
+15
View File
@@ -0,0 +1,15 @@
namespace GlitchyEngine.Threading
{
public class Semaphore
{
public extern this(int32 initialCount = 1, int32 maximumCount = 1);
public const uint32 InfiniteTimeout = 0xFFFFFFFF;
public extern LockResult Lock(uint32 timeout = InfiniteTimeout);
public extern bool Unlock(int32 releaseCount = 1);
public extern bool Unlock(out int32 previousCount, int32 releaseCount = 1);
}
}