mirror of
https://github.com/Ed94/Odin.git
synced 2026-08-06 15:48:51 +00:00
Reimplement sync2.Sema on windows with WaitOnAddress primitives
This commit is contained in:
@@ -153,33 +153,14 @@ cond_broadcast :: proc(c: ^Cond) {
|
|||||||
//
|
//
|
||||||
// A Sema must not be copied after first use
|
// A Sema must not be copied after first use
|
||||||
Sema :: struct {
|
Sema :: struct {
|
||||||
// TODO(bill): Is this implementation too lazy?
|
impl: _Sema,
|
||||||
// Can this be made to work on all OSes without construction and destruction, i.e. Zero is Initialized
|
|
||||||
|
|
||||||
mutex: Mutex,
|
|
||||||
cond: Cond,
|
|
||||||
count: int,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
sema_wait :: proc(s: ^Sema) {
|
sema_wait :: proc(s: ^Sema) {
|
||||||
mutex_lock(&s.mutex);
|
_sema_wait(s);
|
||||||
defer mutex_unlock(&s.mutex);
|
|
||||||
|
|
||||||
for s.count == 0 {
|
|
||||||
cond_wait(&s.cond, &s.mutex);
|
|
||||||
}
|
|
||||||
|
|
||||||
s.count -= 1;
|
|
||||||
if s.count > 0 {
|
|
||||||
cond_signal(&s.cond);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
sema_post :: proc(s: ^Sema, count := 1) {
|
sema_post :: proc(s: ^Sema, count := 1) {
|
||||||
mutex_lock(&s.mutex);
|
_sema_post(s, count);
|
||||||
defer mutex_unlock(&s.mutex);
|
|
||||||
|
|
||||||
s.count += count;
|
|
||||||
cond_signal(&s.cond);
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -240,5 +240,35 @@ _cond_broadcast :: proc(c: ^Cond) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_Sema :: struct {
|
||||||
|
mutex: Mutex,
|
||||||
|
cond: Cond,
|
||||||
|
count: int,
|
||||||
|
}
|
||||||
|
|
||||||
|
_sema_wait :: proc(s: ^Sema) {
|
||||||
|
mutex_lock(&s.impl.mutex);
|
||||||
|
defer mutex_unlock(&s.impl.mutex);
|
||||||
|
|
||||||
|
for s.impl.count == 0 {
|
||||||
|
cond_wait(&s.impl.cond, &s.impl.mutex);
|
||||||
|
}
|
||||||
|
|
||||||
|
s.impl.count -= 1;
|
||||||
|
if s.impl.count > 0 {
|
||||||
|
cond_signal(&s.impl.cond);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_sema_post :: proc(s: ^Sema, count := 1) {
|
||||||
|
mutex_lock(&s.impl.mutex);
|
||||||
|
defer mutex_unlock(&s.impl.mutex);
|
||||||
|
|
||||||
|
s.impl.count += count;
|
||||||
|
cond_signal(&s.impl.cond);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
} // !ODIN_SYNC_USE_PTHREADS
|
} // !ODIN_SYNC_USE_PTHREADS
|
||||||
|
|||||||
@@ -150,5 +150,34 @@ _cond_broadcast :: proc(c: ^Cond) {
|
|||||||
assert(err == 0);
|
assert(err == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_Sema :: struct {
|
||||||
|
mutex: Mutex,
|
||||||
|
cond: Cond,
|
||||||
|
count: int,
|
||||||
|
}
|
||||||
|
|
||||||
|
_sema_wait :: proc(s: ^Sema) {
|
||||||
|
mutex_lock(&s.impl.mutex);
|
||||||
|
defer mutex_unlock(&s.impl.mutex);
|
||||||
|
|
||||||
|
for s.impl.count == 0 {
|
||||||
|
cond_wait(&s.impl.cond, &s.impl.mutex);
|
||||||
|
}
|
||||||
|
|
||||||
|
s.impl.count -= 1;
|
||||||
|
if s.impl.count > 0 {
|
||||||
|
cond_signal(&s.impl.cond);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_sema_post :: proc(s: ^Sema, count := 1) {
|
||||||
|
mutex_lock(&s.impl.mutex);
|
||||||
|
defer mutex_unlock(&s.impl.mutex);
|
||||||
|
|
||||||
|
s.impl.count += count;
|
||||||
|
cond_signal(&s.impl.cond);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
} // ODIN_SYNC_USE_PTHREADS
|
} // ODIN_SYNC_USE_PTHREADS
|
||||||
|
|||||||
@@ -71,3 +71,35 @@ _cond_signal :: proc(c: ^Cond) {
|
|||||||
_cond_broadcast :: proc(c: ^Cond) {
|
_cond_broadcast :: proc(c: ^Cond) {
|
||||||
win32.WakeAllConditionVariable(&c.impl.cond);
|
win32.WakeAllConditionVariable(&c.impl.cond);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
_Sema :: struct {
|
||||||
|
count: int,
|
||||||
|
}
|
||||||
|
|
||||||
|
_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_cxchg(&s.impl.count, original_count-1, original_count) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_sema_post :: proc(s: ^Sema, count := 1) {
|
||||||
|
atomic_add(&s.impl.count, count);
|
||||||
|
if count == 1 {
|
||||||
|
win32.WakeByAddressSingle(&s.impl.count);
|
||||||
|
} else {
|
||||||
|
win32.WakeByAddressAll(&s.impl.count);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user