From 2b18f43b65bc16c921d4f31e61bfcd6d590ab01a Mon Sep 17 00:00:00 2001 From: gingerBill Date: Sat, 27 Jun 2020 00:59:40 +0100 Subject: [PATCH] Update sys/windows; Add sync.Blocking_Mutex (windows only at the moment) --- core/sync/sync_windows.odin | 89 ++++++++++++++++++++++++++++++--- core/sys/windows/kernel32.odin | 3 ++ core/sys/windows/types.odin | 4 +- core/thread/thread_windows.odin | 2 +- 4 files changed, 88 insertions(+), 10 deletions(-) diff --git a/core/sync/sync_windows.odin b/core/sync/sync_windows.odin index f21810598..134e8e806 100644 --- a/core/sync/sync_windows.odin +++ b/core/sync/sync_windows.odin @@ -2,19 +2,25 @@ package sync import win32 "core:sys/windows" +import "core:time" -// A lock that can only be held by one thread at once. Mutex :: struct { _critical_section: win32.CRITICAL_SECTION, } +Blocking_Mutex :: struct { + _handle: win32.SRWLOCK, +} + + +Condition_Mutex_Ptr :: union{^Mutex, ^Blocking_Mutex}; // Blocks until signalled. // When signalled, awakens exactly one waiting thread. Condition :: struct { _handle: win32.CONDITION_VARIABLE, - mutex: ^Mutex, + mutex: Condition_Mutex_Ptr, } // When waited upon, blocks until the internal count is greater than zero, then subtracts one. @@ -23,6 +29,10 @@ Semaphore :: struct { _handle: win32.HANDLE, } +RW_Lock :: struct { + _handle: win32.SRWLOCK, +} + semaphore_init :: proc(s: ^Semaphore, initial_count := 0) { s._handle = win32.CreateSemaphoreW(nil, i32(initial_count), 1<<31-1, nil); @@ -63,7 +73,28 @@ mutex_unlock :: proc(m: ^Mutex) { win32.LeaveCriticalSection(&m._critical_section); } -condition_init :: proc(c: ^Condition, mutex: ^Mutex) -> bool { +blocking_mutex_init :: proc(m: ^Blocking_Mutex) { + // +} + +blocking_mutex_destroy :: proc(m: ^Blocking_Mutex) { + // +} + +blocking_mutex_lock :: proc(m: ^Blocking_Mutex) { + win32.AcquireSRWLockExclusive(&m._handle); +} + +blocking_mutex_try_lock :: proc(m: ^Blocking_Mutex) -> bool { + return bool(win32.TryAcquireSRWLockExclusive(&m._handle)); +} + +blocking_mutex_unlock :: proc(m: ^Blocking_Mutex) { + win32.ReleaseSRWLockExclusive(&m._handle); +} + + +condition_init :: proc(c: ^Condition, mutex: Condition_Mutex_Ptr) -> bool { assert(mutex != nil); win32.InitializeConditionVariable(&c._handle); c.mutex = mutex; @@ -71,9 +102,7 @@ condition_init :: proc(c: ^Condition, mutex: ^Mutex) -> bool { } condition_destroy :: proc(c: ^Condition) { - if c._handle.ptr != nil { - win32.WakeAllConditionVariable(&c._handle); - } + // } condition_signal :: proc(c: ^Condition) -> bool { @@ -93,5 +122,51 @@ condition_broadcast :: proc(c: ^Condition) -> bool { } condition_wait_for :: proc(c: ^Condition) -> bool { - return cast(bool)win32.SleepConditionVariableCS(&c._handle, &c.mutex._critical_section, win32.INFINITE); + switch m in &c.mutex { + case ^Mutex: + return cast(bool)win32.SleepConditionVariableCS(&c._handle, &m._critical_section, win32.INFINITE); + case ^Blocking_Mutex: + return cast(bool)win32.SleepConditionVariableSRW(&c._handle, &m._handle, win32.INFINITE, 0); + } + return false; } +condition_wait_for_timeout :: proc(c: ^Condition, duration: time.Duration) -> bool { + ms := win32.DWORD((time.duration_nanoseconds(duration) + 999999)/1000000); + switch m in &c.mutex { + case ^Mutex: + return cast(bool)win32.SleepConditionVariableCS(&c._handle, &m._critical_section, ms); + case ^Blocking_Mutex: + return cast(bool)win32.SleepConditionVariableSRW(&c._handle, &m._handle, ms, 0); + } + return false; +} + + + +rw_lock_init :: proc(l: ^RW_Lock) { + l._handle = win32.SRWLOCK_INIT; +} +rw_lock_destroy :: proc(l: ^RW_Lock) { + // +} +rw_lock_read :: proc(l: ^RW_Lock) { + win32.AcquireSRWLockShared(&l._handle); +} +rw_lock_try_read :: proc(l: ^RW_Lock) -> bool { + return bool(win32.TryAcquireSRWLockShared(&l._handle)); +} +rw_lock_write :: proc(l: ^RW_Lock) { + win32.AcquireSRWLockExclusive(&l._handle); +} +rw_lock_try_write :: proc(l: ^RW_Lock) -> bool { + return bool(win32.TryAcquireSRWLockExclusive(&l._handle)); +} +rw_lock_read_unlock :: proc(l: ^RW_Lock) { + win32.ReleaseSRWLockShared(&l._handle); +} +rw_lock_write_unlock :: proc(l: ^RW_Lock) { + win32.ReleaseSRWLockExclusive(&l._handle); +} + + + diff --git a/core/sys/windows/kernel32.odin b/core/sys/windows/kernel32.odin index bea14deff..bcebe91a2 100644 --- a/core/sys/windows/kernel32.odin +++ b/core/sys/windows/kernel32.odin @@ -245,6 +245,9 @@ foreign kernel32 { AcquireSRWLockExclusive :: proc(SRWLock: ^SRWLOCK) --- TryAcquireSRWLockExclusive :: proc(SRWLock: ^SRWLOCK) -> BOOL --- ReleaseSRWLockExclusive :: proc(SRWLock: ^SRWLOCK) --- + AcquireSRWLockShared :: proc(SRWLock: ^SRWLOCK) --- + TryAcquireSRWLockShared :: proc(SRWLock: ^SRWLOCK) -> BOOL --- + ReleaseSRWLockShared :: proc(SRWLock: ^SRWLOCK) --- InitializeConditionVariable :: proc(ConditionVariable: ^CONDITION_VARIABLE) --- WakeConditionVariable :: proc(ConditionVariable: ^CONDITION_VARIABLE) --- diff --git a/core/sys/windows/types.odin b/core/sys/windows/types.odin index dd7f8377c..e9f2b495a 100644 --- a/core/sys/windows/types.odin +++ b/core/sys/windows/types.odin @@ -63,7 +63,7 @@ PCONDITION_VARIABLE :: ^CONDITION_VARIABLE; PLARGE_INTEGER :: ^LARGE_INTEGER; PSRWLOCK :: ^SRWLOCK; -SOCKET :: distinct rawptr; // TODO +SOCKET :: distinct uintptr; // TODO socklen_t :: c_int; ADDRESS_FAMILY :: USHORT; @@ -147,7 +147,7 @@ WSA_FLAG_NO_HANDLE_INHERIT: DWORD : 0x80; WSADESCRIPTION_LEN :: 256; WSASYS_STATUS_LEN :: 128; WSAPROTOCOL_LEN: DWORD : 255; -INVALID_SOCKET :: SOCKET(~uintptr(0)); +INVALID_SOCKET :: ~SOCKET(0); WSAEACCES: c_int : 10013; WSAEINVAL: c_int : 10022; diff --git a/core/thread/thread_windows.odin b/core/thread/thread_windows.odin index e1627ad2c..5d0a4600c 100644 --- a/core/thread/thread_windows.odin +++ b/core/thread/thread_windows.odin @@ -95,5 +95,5 @@ terminate :: proc(using thread : ^Thread, exit_code: u32) { } yield :: proc() { - win32.Sleep(0); + win32.SwitchToThread(); }