|
@@ -1,23 +1,20 @@
|
|
|
// +build windows
|
|
|
package sync
|
|
|
|
|
|
-import win32 "core:sys/windows"
|
|
|
+import "core:sys/win32"
|
|
|
|
|
|
+foreign import kernel32 "system:kernel32.lib"
|
|
|
|
|
|
+// A lock that can only be held by one thread at once.
|
|
|
Mutex :: struct {
|
|
|
- _handle: win32.SRWLOCK,
|
|
|
-
|
|
|
-}
|
|
|
-
|
|
|
-Recursive_Mutex :: struct {
|
|
|
- _handle: win32.CRITICAL_SECTION,
|
|
|
+ _critical_section: win32.Critical_Section,
|
|
|
}
|
|
|
|
|
|
|
|
|
// Blocks until signalled.
|
|
|
// When signalled, awakens exactly one waiting thread.
|
|
|
Condition :: struct {
|
|
|
- _handle: win32.CONDITION_VARIABLE,
|
|
|
+ _handle: WIN32_CONDITION_VARIABLE,
|
|
|
|
|
|
mutex: ^Mutex,
|
|
|
}
|
|
@@ -25,98 +22,87 @@ Condition :: struct {
|
|
|
// When waited upon, blocks until the internal count is greater than zero, then subtracts one.
|
|
|
// Posting to the semaphore increases the count by one, or the provided amount.
|
|
|
Semaphore :: struct {
|
|
|
- _handle: win32.HANDLE,
|
|
|
+ _handle: win32.Handle,
|
|
|
}
|
|
|
|
|
|
|
|
|
semaphore_init :: proc(s: ^Semaphore, initial_count := 0) {
|
|
|
- s._handle = win32.CreateSemaphoreW(nil, win32.LONG(initial_count), 1<<31-1, nil);
|
|
|
+ s._handle = win32.create_semaphore_w(nil, i32(initial_count), 1<<31-1, nil);
|
|
|
}
|
|
|
|
|
|
semaphore_destroy :: proc(s: ^Semaphore) {
|
|
|
- win32.CloseHandle(s._handle);
|
|
|
+ win32.close_handle(s._handle);
|
|
|
}
|
|
|
|
|
|
semaphore_post :: proc(s: ^Semaphore, count := 1) {
|
|
|
- win32.ReleaseSemaphore(s._handle, win32.LONG(count), nil);
|
|
|
+ win32.release_semaphore(s._handle, i32(count), nil);
|
|
|
}
|
|
|
|
|
|
semaphore_wait_for :: proc(s: ^Semaphore) {
|
|
|
- // NOTE(tetra, 2019-10-30): WaitForSingleObject decrements the count before it returns.
|
|
|
- result := win32.WaitForSingleObject(s._handle, win32.INFINITE);
|
|
|
+ // NOTE(tetra, 2019-10-30): wait_for_single_object decrements the count before it returns.
|
|
|
+ result := win32.wait_for_single_object(s._handle, win32.INFINITE);
|
|
|
assert(result != win32.WAIT_FAILED);
|
|
|
}
|
|
|
|
|
|
|
|
|
mutex_init :: proc(m: ^Mutex, spin_count := 0) {
|
|
|
- win32.InitializeSRWLock(&m._handle);
|
|
|
+ win32.initialize_critical_section_and_spin_count(&m._critical_section, u32(spin_count));
|
|
|
}
|
|
|
|
|
|
mutex_destroy :: proc(m: ^Mutex) {
|
|
|
- win32.ReleaseSRWLockExclusive(&m._handle);
|
|
|
+ win32.delete_critical_section(&m._critical_section);
|
|
|
}
|
|
|
|
|
|
mutex_lock :: proc(m: ^Mutex) {
|
|
|
- win32.AcquireSRWLockExclusive(&m._handle);
|
|
|
+ win32.enter_critical_section(&m._critical_section);
|
|
|
}
|
|
|
|
|
|
mutex_try_lock :: proc(m: ^Mutex) -> bool {
|
|
|
- return bool(win32.TryAcquireSRWLockExclusive(&m._handle));
|
|
|
+ return bool(win32.try_enter_critical_section(&m._critical_section));
|
|
|
}
|
|
|
|
|
|
mutex_unlock :: proc(m: ^Mutex) {
|
|
|
- win32.ReleaseSRWLockExclusive(&m._handle);
|
|
|
-}
|
|
|
-
|
|
|
-
|
|
|
-recursive_mutex_init :: proc(m: ^Recursive_Mutex, spin_count := 0) {
|
|
|
- win32.InitializeCriticalSectionAndSpinCount(&m._handle, u32(spin_count));
|
|
|
-}
|
|
|
-
|
|
|
-recursive_mutex_destroy :: proc(m: ^Recursive_Mutex) {
|
|
|
- win32.DeleteCriticalSection(&m._handle);
|
|
|
-}
|
|
|
-
|
|
|
-recursive_mutex_lock :: proc(m: ^Recursive_Mutex) {
|
|
|
- win32.EnterCriticalSection(&m._handle);
|
|
|
+ win32.leave_critical_section(&m._critical_section);
|
|
|
}
|
|
|
|
|
|
-recursive_mutex_try_lock :: proc(m: ^Recursive_Mutex) -> bool {
|
|
|
- return bool(win32.TryEnterCriticalSection(&m._handle));
|
|
|
-}
|
|
|
-
|
|
|
-recursive_mutex_unlock :: proc(m: ^Recursive_Mutex) {
|
|
|
- win32.LeaveCriticalSection(&m._handle);
|
|
|
+@private WIN32_CONDITION_VARIABLE :: distinct rawptr;
|
|
|
+@private
|
|
|
+foreign kernel32 {
|
|
|
+ InitializeConditionVariable :: proc(ConditionVariable: ^WIN32_CONDITION_VARIABLE) ---
|
|
|
+ WakeConditionVariable :: proc(ConditionVariable: ^WIN32_CONDITION_VARIABLE) ---
|
|
|
+ WakeAllConditionVariable :: proc(ConditionVariable: ^WIN32_CONDITION_VARIABLE) ---
|
|
|
+ SleepConditionVariableCS :: proc(ConditionVariable: ^WIN32_CONDITION_VARIABLE, CriticalSection: ^win32.Critical_Section, dwMilliseconds: u32) -> b32 ---
|
|
|
}
|
|
|
|
|
|
condition_init :: proc(c: ^Condition, mutex: ^Mutex) -> bool {
|
|
|
assert(mutex != nil);
|
|
|
- win32.InitializeConditionVariable(&c._handle);
|
|
|
+ InitializeConditionVariable(&c._handle);
|
|
|
c.mutex = mutex;
|
|
|
- return true;
|
|
|
+ return c._handle != nil;
|
|
|
}
|
|
|
|
|
|
condition_destroy :: proc(c: ^Condition) {
|
|
|
- // Does nothing
|
|
|
+ if c._handle != nil {
|
|
|
+ WakeAllConditionVariable(&c._handle);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
condition_signal :: proc(c: ^Condition) -> bool {
|
|
|
- if c._handle.ptr == nil {
|
|
|
+ if c._handle == nil {
|
|
|
return false;
|
|
|
}
|
|
|
- win32.WakeConditionVariable(&c._handle);
|
|
|
+ WakeConditionVariable(&c._handle);
|
|
|
return true;
|
|
|
}
|
|
|
|
|
|
condition_broadcast :: proc(c: ^Condition) -> bool {
|
|
|
- if c._handle.ptr == nil {
|
|
|
+ if c._handle == nil {
|
|
|
return false;
|
|
|
}
|
|
|
- win32.WakeAllConditionVariable(&c._handle);
|
|
|
+ WakeAllConditionVariable(&c._handle);
|
|
|
return true;
|
|
|
}
|
|
|
|
|
|
condition_wait_for :: proc(c: ^Condition) -> bool {
|
|
|
- res := win32.SleepConditionVariableSRW(&c._handle, &c.mutex._handle, win32.INFINITE, 0);
|
|
|
- return bool(res);
|
|
|
+ return cast(bool)SleepConditionVariableCS(&c._handle, &c.mutex._critical_section, win32.INFINITE);
|
|
|
}
|