//+build windows //+private package sync2 import "core:time" import win32 "core:sys/windows" _current_thread_id :: proc "contextless" () -> int { return int(win32.GetCurrentThreadId()); } _Mutex :: struct { srwlock: win32.SRWLOCK, } _mutex_lock :: proc(m: ^Mutex) { win32.AcquireSRWLockExclusive(&m.impl.srwlock); } _mutex_unlock :: proc(m: ^Mutex) { win32.ReleaseSRWLockExclusive(&m.impl.srwlock); } _mutex_try_lock :: proc(m: ^Mutex) -> bool { return bool(win32.TryAcquireSRWLockExclusive(&m.impl.srwlock)); } _RW_Mutex :: struct { srwlock: win32.SRWLOCK, } _rw_mutex_lock :: proc(rw: ^RW_Mutex) { win32.AcquireSRWLockExclusive(&rw.impl.srwlock); } _rw_mutex_unlock :: proc(rw: ^RW_Mutex) { win32.ReleaseSRWLockExclusive(&rw.impl.srwlock); } _rw_mutex_try_lock :: proc(rw: ^RW_Mutex) -> bool { return bool(win32.TryAcquireSRWLockExclusive(&rw.impl.srwlock)); } _rw_mutex_shared_lock :: proc(rw: ^RW_Mutex) { win32.AcquireSRWLockShared(&rw.impl.srwlock); } _rw_mutex_shared_unlock :: proc(rw: ^RW_Mutex) { win32.ReleaseSRWLockShared(&rw.impl.srwlock); } _rw_mutex_try_shared_lock :: proc(rw: ^RW_Mutex) -> bool { return bool(win32.TryAcquireSRWLockShared(&rw.impl.srwlock)); } _Recursive_Mutex :: struct { owner: u32, claim_count: i32, } _recursive_mutex_lock :: proc(m: ^Recursive_Mutex) { tid := win32.GetCurrentThreadId(); for { prev_owner := atomic_compare_exchange_strong_acquire(&m.impl.owner, tid, 0); switch prev_owner { case 0, tid: m.impl.claim_count += 1; // inside the lock return; } win32.WaitOnAddress( &m.impl.owner, &prev_owner, size_of(prev_owner), win32.INFINITE, ); } } _recursive_mutex_unlock :: proc(m: ^Recursive_Mutex) { m.impl.claim_count -= 1; if m.impl.claim_count != 0 { return; } atomic_exchange_release(&m.impl.owner, 0); win32.WakeByAddressSingle(&m.impl.owner); // outside the lock } _recursive_mutex_try_lock :: proc(m: ^Recursive_Mutex) -> bool { tid := win32.GetCurrentThreadId(); prev_owner := atomic_compare_exchange_strong_acquire(&m.impl.owner, tid, 0); switch prev_owner { case 0, tid: m.impl.claim_count += 1; // inside the lock return true; } return false; } _Cond :: struct { cond: win32.CONDITION_VARIABLE, } _cond_wait :: proc(c: ^Cond, m: ^Mutex) { _ = win32.SleepConditionVariableSRW(&c.impl.cond, &m.impl.srwlock, win32.INFINITE, 0); } _cond_wait_with_timeout :: proc(c: ^Cond, m: ^Mutex, timeout: time.Duration) -> bool { ms := win32.DWORD((max(time.duration_nanoseconds(timeout), 0) + 999999)/1000000); return cast(bool)win32.SleepConditionVariableSRW(&c.impl.cond, &m.impl.srwlock, ms, 0); } _cond_signal :: proc(c: ^Cond) { win32.WakeConditionVariable(&c.impl.cond); } _cond_broadcast :: proc(c: ^Cond) { win32.WakeAllConditionVariable(&c.impl.cond); } _Sema :: struct { count: i32, } _sema_wait :: proc(s: ^Sema) { for { original_count := s.impl.count; for original_count == 0 { win32.WaitOnAddress( &s.impl.count, &original_count, size_of(original_count), win32.INFINITE, ); original_count = s.impl.count; } if original_count == atomic_compare_exchange_strong(&s.impl.count, original_count-1, original_count) { return; } } } _sema_post :: proc(s: ^Sema, count := 1) { atomic_add(&s.impl.count, i32(count)); if count == 1 { win32.WakeByAddressSingle(&s.impl.count); } else { win32.WakeByAddressAll(&s.impl.count); } }