mirror of
https://github.com/odin-lang/Odin.git
synced 2025-12-29 01:14:40 +00:00
82 lines
1.9 KiB
Odin
82 lines
1.9 KiB
Odin
package sync
|
|
|
|
|
|
// A barrier enabling multiple threads to synchronize the beginning of some computation
|
|
/*
|
|
* Example:
|
|
*
|
|
* package example
|
|
*
|
|
* import "core:fmt"
|
|
* import "core:sync"
|
|
* import "core:thread"
|
|
*
|
|
* barrier := &sync.Barrier{};
|
|
*
|
|
* main :: proc() {
|
|
* fmt.println("Start");
|
|
*
|
|
* THREAD_COUNT :: 4;
|
|
* threads: [THREAD_COUNT]^thread.Thread;
|
|
*
|
|
* sync.barrier_init(barrier, THREAD_COUNT);
|
|
* defer sync.barrier_destroy(barrier);
|
|
*
|
|
*
|
|
* for _, i in threads {
|
|
* threads[i] = thread.create_and_start(proc(t: ^thread.Thread) {
|
|
* // Same messages will be printed together but without any interleaving
|
|
* fmt.println("Getting ready!");
|
|
* sync.barrier_wait(barrier);
|
|
* fmt.println("Off their marks they go!");
|
|
* });
|
|
* }
|
|
*
|
|
* for t in threads {
|
|
* thread.destroy(t); // join and free thread
|
|
* }
|
|
* fmt.println("Finished");
|
|
* }
|
|
*
|
|
*/
|
|
Barrier :: struct {
|
|
mutex: Blocking_Mutex,
|
|
cond: Condition,
|
|
index: int,
|
|
generation_id: int,
|
|
thread_count: int,
|
|
}
|
|
|
|
barrier_init :: proc(b: ^Barrier, thread_count: int) {
|
|
blocking_mutex_init(&b.mutex);
|
|
condition_init(&b.cond, &b.mutex);
|
|
b.index = 0;
|
|
b.generation_id = 0;
|
|
b.thread_count = thread_count;
|
|
}
|
|
|
|
barrier_destroy :: proc(b: ^Barrier) {
|
|
blocking_mutex_destroy(&b.mutex);
|
|
condition_destroy(&b.cond);
|
|
}
|
|
|
|
// Block the current thread until all threads have rendezvoused
|
|
// Barrier can be reused after all threads rendezvoused once, and can be used continuously
|
|
barrier_wait :: proc(b: ^Barrier) -> (is_leader: bool) {
|
|
blocking_mutex_lock(&b.mutex);
|
|
defer blocking_mutex_unlock(&b.mutex);
|
|
local_gen := b.generation_id;
|
|
b.index += 1;
|
|
if b.index < b.thread_count {
|
|
for local_gen == b.generation_id && b.index < b.thread_count {
|
|
condition_wait_for(&b.cond);
|
|
}
|
|
return false;
|
|
}
|
|
|
|
b.index = 0;
|
|
b.generation_id += 1;
|
|
condition_broadcast(&b.cond);
|
|
return true;
|
|
}
|