From 4b032d2c7ee7737013d13bb647001a0396900ff6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20L=C3=BCbe=C3=9F?= Date: Wed, 3 Mar 2021 18:57:42 +0100 Subject: [PATCH] Added Semaphore and Mutex --- .../Windows/Threading/WindowsMutex.bf | 49 +++++++++++++++++ .../Windows/Threading/WindowsSemaphore.bf | 55 +++++++++++++++++++ .../src/Platform/Windows/WindowsExtension.bf | 38 +++++++++++++ GlitchyEngine/src/Threading/LockResult.bf | 24 ++++++++ GlitchyEngine/src/Threading/Mutex.bf | 13 +++++ GlitchyEngine/src/Threading/Semaphore.bf | 15 +++++ 6 files changed, 194 insertions(+) create mode 100644 GlitchyEngine/src/Platform/Windows/Threading/WindowsMutex.bf create mode 100644 GlitchyEngine/src/Platform/Windows/Threading/WindowsSemaphore.bf create mode 100644 GlitchyEngine/src/Platform/Windows/WindowsExtension.bf create mode 100644 GlitchyEngine/src/Threading/LockResult.bf create mode 100644 GlitchyEngine/src/Threading/Mutex.bf create mode 100644 GlitchyEngine/src/Threading/Semaphore.bf diff --git a/GlitchyEngine/src/Platform/Windows/Threading/WindowsMutex.bf b/GlitchyEngine/src/Platform/Windows/Threading/WindowsMutex.bf new file mode 100644 index 0000000..4d84b8f --- /dev/null +++ b/GlitchyEngine/src/Platform/Windows/Threading/WindowsMutex.bf @@ -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 diff --git a/GlitchyEngine/src/Platform/Windows/Threading/WindowsSemaphore.bf b/GlitchyEngine/src/Platform/Windows/Threading/WindowsSemaphore.bf new file mode 100644 index 0000000..c28faf0 --- /dev/null +++ b/GlitchyEngine/src/Platform/Windows/Threading/WindowsSemaphore.bf @@ -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 \ No newline at end of file diff --git a/GlitchyEngine/src/Platform/Windows/WindowsExtension.bf b/GlitchyEngine/src/Platform/Windows/WindowsExtension.bf new file mode 100644 index 0000000..3d3fe44 --- /dev/null +++ b/GlitchyEngine/src/Platform/Windows/WindowsExtension.bf @@ -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); + } +} diff --git a/GlitchyEngine/src/Threading/LockResult.bf b/GlitchyEngine/src/Threading/LockResult.bf new file mode 100644 index 0000000..1484995 --- /dev/null +++ b/GlitchyEngine/src/Threading/LockResult.bf @@ -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 + } +} diff --git a/GlitchyEngine/src/Threading/Mutex.bf b/GlitchyEngine/src/Threading/Mutex.bf new file mode 100644 index 0000000..b9253e4 --- /dev/null +++ b/GlitchyEngine/src/Threading/Mutex.bf @@ -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(); + } +} diff --git a/GlitchyEngine/src/Threading/Semaphore.bf b/GlitchyEngine/src/Threading/Semaphore.bf new file mode 100644 index 0000000..3cfa8b8 --- /dev/null +++ b/GlitchyEngine/src/Threading/Semaphore.bf @@ -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); + } +} \ No newline at end of file