mirror of
https://github.com/Ed94/Odin.git
synced 2026-08-05 23:28:48 +00:00
Add utility procedure groups for sync primitives
This commit is contained in:
@@ -77,31 +77,31 @@ wait_group_wait_with_timeout :: proc(wg: ^Wait_Group, duration: time.Duration) -
|
|||||||
* import "core:sync"
|
* import "core:sync"
|
||||||
* import "core:thread"
|
* import "core:thread"
|
||||||
*
|
*
|
||||||
* barrier := &sync.Barrier{};
|
* barrier := &sync.Barrier{}
|
||||||
*
|
*
|
||||||
* main :: proc() {
|
* main :: proc() {
|
||||||
* fmt.println("Start");
|
* fmt.println("Start")
|
||||||
*
|
*
|
||||||
* THREAD_COUNT :: 4;
|
* THREAD_COUNT :: 4
|
||||||
* threads: [THREAD_COUNT]^thread.Thread;
|
* threads: [THREAD_COUNT]^thread.Thread
|
||||||
*
|
*
|
||||||
* sync.barrier_init(barrier, THREAD_COUNT);
|
* sync.barrier_init(barrier, THREAD_COUNT)
|
||||||
* defer sync.barrier_destroy(barrier);
|
* defer sync.barrier_destroy(barrier)
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* for _, i in threads {
|
* for _, i in threads {
|
||||||
* threads[i] = thread.create_and_start(proc(t: ^thread.Thread) {
|
* threads[i] = thread.create_and_start(proc(t: ^thread.Thread) {
|
||||||
* // Same messages will be printed together but without any interleaving
|
* // Same messages will be printed together but without any interleaving
|
||||||
* fmt.println("Getting ready!");
|
* fmt.println("Getting ready!")
|
||||||
* sync.barrier_wait(barrier);
|
* sync.barrier_wait(barrier)
|
||||||
* fmt.println("Off their marks they go!");
|
* fmt.println("Off their marks they go!")
|
||||||
* });
|
* })
|
||||||
* }
|
* }
|
||||||
*
|
*
|
||||||
* for t in threads {
|
* for t in threads {
|
||||||
* thread.destroy(t); // join and free thread
|
* thread.destroy(t) // join and free thread
|
||||||
* }
|
* }
|
||||||
* fmt.println("Finished");
|
* fmt.println("Finished")
|
||||||
* }
|
* }
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
@@ -186,7 +186,11 @@ ticket_mutex_lock :: #force_inline proc(m: ^Ticket_Mutex) {
|
|||||||
ticket_mutex_unlock :: #force_inline proc(m: ^Ticket_Mutex) {
|
ticket_mutex_unlock :: #force_inline proc(m: ^Ticket_Mutex) {
|
||||||
atomic_add_relaxed(&m.serving, 1)
|
atomic_add_relaxed(&m.serving, 1)
|
||||||
}
|
}
|
||||||
|
@(deferred_in=ticket_mutex_unlock)
|
||||||
|
ticket_mutex_guard :: proc(m: ^Ticket_Mutex) -> bool {
|
||||||
|
ticket_mutex_lock(m)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
Benaphore :: struct {
|
Benaphore :: struct {
|
||||||
@@ -211,6 +215,12 @@ benaphore_unlock :: proc(b: ^Benaphore) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@(deferred_in=benaphore_unlock)
|
||||||
|
benaphore_guard :: proc(m: ^Benaphore) -> bool {
|
||||||
|
benaphore_lock(m)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
Recursive_Benaphore :: struct {
|
Recursive_Benaphore :: struct {
|
||||||
counter: int,
|
counter: int,
|
||||||
owner: int,
|
owner: int,
|
||||||
@@ -261,15 +271,24 @@ recursive_benaphore_unlock :: proc(b: ^Recursive_Benaphore) {
|
|||||||
// outside the lock
|
// outside the lock
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@(deferred_in=recursive_benaphore_unlock)
|
||||||
|
recursive_benaphore_guard :: proc(m: ^Recursive_Benaphore) -> bool {
|
||||||
|
recursive_benaphore_lock(m)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Once is a data value that will perform exactly on action.
|
||||||
|
//
|
||||||
|
// A Once must not be copied after first use.
|
||||||
Once :: struct {
|
Once :: struct {
|
||||||
m: Mutex,
|
m: Mutex,
|
||||||
done: bool,
|
done: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// once_do calls the procedure fn if and only if once_do is being called for the first for this instance of Once.
|
||||||
once_do :: proc(o: ^Once, fn: proc()) {
|
once_do :: proc(o: ^Once, fn: proc()) {
|
||||||
@(cold)
|
@(cold)
|
||||||
do_slow :: proc(o: ^Once, fn: proc()) {
|
do_slow :: proc(o: ^Once, fn: proc()) {
|
||||||
|
|||||||
@@ -409,6 +409,14 @@ Atomic_Sema :: struct {
|
|||||||
count: int,
|
count: int,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
atomic_sema_post :: proc(s: ^Atomic_Sema, count := 1) {
|
||||||
|
atomic_mutex_lock(&s.mutex)
|
||||||
|
defer atomic_mutex_unlock(&s.mutex)
|
||||||
|
|
||||||
|
s.count += count
|
||||||
|
atomic_cond_signal(&s.cond)
|
||||||
|
}
|
||||||
|
|
||||||
atomic_sema_wait :: proc(s: ^Atomic_Sema) {
|
atomic_sema_wait :: proc(s: ^Atomic_Sema) {
|
||||||
atomic_mutex_lock(&s.mutex)
|
atomic_mutex_lock(&s.mutex)
|
||||||
defer atomic_mutex_unlock(&s.mutex)
|
defer atomic_mutex_unlock(&s.mutex)
|
||||||
@@ -423,11 +431,29 @@ atomic_sema_wait :: proc(s: ^Atomic_Sema) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
atomic_sema_post :: proc(s: ^Atomic_Sema, count := 1) {
|
atomic_sema_wait_with_timeout :: proc(s: ^Atomic_Sema, duration: time.Duration) -> bool {
|
||||||
|
if duration <= 0 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
atomic_mutex_lock(&s.mutex)
|
atomic_mutex_lock(&s.mutex)
|
||||||
defer atomic_mutex_unlock(&s.mutex)
|
defer atomic_mutex_unlock(&s.mutex)
|
||||||
|
|
||||||
|
start := time.tick_now()
|
||||||
|
|
||||||
s.count += count
|
for s.count == 0 {
|
||||||
atomic_cond_signal(&s.cond)
|
remaining := duration - time.tick_since(start)
|
||||||
|
if remaining < 0 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if !atomic_cond_wait_with_timeout(&s.cond, &s.mutex, remaining) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
s.count -= 1
|
||||||
|
if s.count > 0 {
|
||||||
|
atomic_cond_signal(&s.cond)
|
||||||
|
}
|
||||||
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,80 @@
|
|||||||
|
package sync2
|
||||||
|
|
||||||
|
|
||||||
|
guard :: proc{
|
||||||
|
mutex_guard,
|
||||||
|
rw_mutex_guard,
|
||||||
|
ticket_mutex_guard,
|
||||||
|
benaphore_guard,
|
||||||
|
recursive_benaphore_guard,
|
||||||
|
atomic_mutex_guard,
|
||||||
|
atomic_recursive_mutex_guard,
|
||||||
|
}
|
||||||
|
|
||||||
|
shared_guard :: proc{
|
||||||
|
rw_mutex_shared_guard,
|
||||||
|
atomic_rw_mutex_shared_guard,
|
||||||
|
}
|
||||||
|
|
||||||
|
lock :: proc{
|
||||||
|
mutex_lock,
|
||||||
|
rw_mutex_lock,
|
||||||
|
ticket_mutex_lock,
|
||||||
|
benaphore_lock,
|
||||||
|
recursive_benaphore_lock,
|
||||||
|
atomic_mutex_lock,
|
||||||
|
atomic_recursive_mutex_lock,
|
||||||
|
}
|
||||||
|
|
||||||
|
unlock :: proc{
|
||||||
|
mutex_unlock,
|
||||||
|
rw_mutex_unlock,
|
||||||
|
ticket_mutex_unlock,
|
||||||
|
benaphore_unlock,
|
||||||
|
recursive_benaphore_unlock,
|
||||||
|
atomic_mutex_unlock,
|
||||||
|
atomic_recursive_mutex_unlock,
|
||||||
|
}
|
||||||
|
|
||||||
|
try_lock :: proc{
|
||||||
|
mutex_try_lock,
|
||||||
|
rw_mutex_try_lock,
|
||||||
|
benaphore_try_lock,
|
||||||
|
recursive_benaphore_try_lock,
|
||||||
|
atomic_mutex_try_lock,
|
||||||
|
atomic_recursive_mutex_try_lock,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
wait :: proc{
|
||||||
|
cond_wait,
|
||||||
|
sema_wait,
|
||||||
|
atomic_cond_wait,
|
||||||
|
atomic_sema_wait,
|
||||||
|
futex_wait,
|
||||||
|
}
|
||||||
|
|
||||||
|
wait_for_timeout :: proc{
|
||||||
|
cond_wait_with_timeout,
|
||||||
|
sema_wait_with_timeout,
|
||||||
|
atomic_cond_wait_with_timeout,
|
||||||
|
atomic_sema_wait_with_timeout,
|
||||||
|
futex_wait_with_timeout,
|
||||||
|
}
|
||||||
|
|
||||||
|
post :: proc{
|
||||||
|
sema_post,
|
||||||
|
atomic_sema_post,
|
||||||
|
}
|
||||||
|
|
||||||
|
signal :: proc{
|
||||||
|
cond_signal,
|
||||||
|
atomic_cond_signal,
|
||||||
|
futex_signal,
|
||||||
|
}
|
||||||
|
|
||||||
|
broadcast :: proc{
|
||||||
|
cond_broadcast,
|
||||||
|
atomic_cond_broadcast,
|
||||||
|
futex_broadcast,
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user