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; }