package core:sync

Index

Variables (0)

This section is empty.

Procedures (99)

Types

Atomic_Cond ¶

Atomic_Cond :: struct {
	state: Futex,
}
 

Atomic_Cond implements a condition variable, a rendezvous point for threads waiting for signalling the occurence of an event

An Atomic_Cond must not be copied after first use

Atomic_Memory_Order ¶

Atomic_Memory_Order :: .Atomic_Memory_Order
 

Atomic_Memory_Order :: enum {

Relaxed = 0, // Unordered
Consume = 1, // Monotonic
Acquire = 2,
Release = 3,
Acq_Rel = 4,
Seq_Cst = 5,

}

Atomic_Mutex ¶

Atomic_Mutex :: struct {
	state: Atomic_Mutex_State,
}
 

An Atomic_Mutex is a mutual exclusion lock The zero value for a Atomic_Mutex is an unlocked mutex

An Atomic_Mutex must not be copied after first use

Atomic_Mutex_State ¶

Atomic_Mutex_State :: enum Futex {
	Unlocked = 0, 
	Locked   = 1, 
	Waiting  = 2, 
}

Atomic_RW_Mutex ¶

Atomic_RW_Mutex :: struct {
	state: Atomic_RW_Mutex_State,
	mutex: Atomic_Mutex,
	sema:  Atomic_Sema,
}
 

An Atomic_RW_Mutex is a reader/writer mutual exclusion lock The lock can be held by any arbitrary number of readers or a single writer The zero value for an Atomic_RW_Mutex is an unlocked mutex

An Atomic_RW_Mutex must not be copied after first use

Atomic_RW_Mutex_State ¶

Atomic_RW_Mutex_State :: distinct uint

Atomic_Recursive_Mutex ¶

Atomic_Recursive_Mutex :: struct {
	owner:     int,
	recursion: int,
	mutex:     Mutex,
}
 

An Atomic_Recursive_Mutex is a recursive mutual exclusion lock The zero value for a Recursive_Mutex is an unlocked mutex

An Atomic_Recursive_Mutex must not be copied after first use

Atomic_Sema ¶

Atomic_Sema :: struct {
	count: Futex,
}
 

When waited upon, blocks until the internal count is greater than zero, then subtracts one. Posting to the semaphore increases the count by one, or the provided amount.

An Atomic_Sema must not be copied after first use

Auto_Reset_Event ¶

Auto_Reset_Event :: struct {
	// status ==  0: Event is reset and no threads are waiting
	// status ==  1: Event is signaled
	// status == -N: Event is reset and N threads are waiting
	status: i32,
	sema:   Sema,
}

Barrier ¶

Barrier :: struct {
	mutex:         Mutex,
	cond:          Cond,
	index:         int,
	generation_id: int,
	thread_count:  int,
}
 

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)

	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")
}

Benaphore ¶

Benaphore :: struct {
	counter: i32,
	sema:    Sema,
}

Cond ¶

Cond :: struct {
	impl: _Cond,
}
 

Cond implements a condition variable, a rendezvous point for threads waiting for signalling the occurence of an event

A Cond must not be copied after first use

Futex ¶

Futex :: distinct u32
 

Futex is a fast userspace mutual exclusion lock, using a 32-bit memory address as a hint

An Futex must not be copied after first use

Mutex ¶

Mutex :: struct {
	impl: _Mutex,
}
 

A Mutex is a mutual exclusion lock The zero value for a Mutex is an unlocked mutex

A Mutex must not be copied after first use

Once ¶

Once :: struct {
	m:    Mutex,
	done: bool,
}
 

Once is a data value that will perform exactly on action.

A Once must not be copied after first use.

Parker ¶

Parker :: struct {
	state: Futex,
}
 

A Parker is an associated token which is initially not present: * The park procedure blocks the current thread unless or until the token is available, at which point the token is consumed. * The park_with_timeout procedures works the same as park but only blocks for the specified duration. * The unpark procedure automatically makes the token available if it was not already.

RW_Mutex ¶

RW_Mutex :: struct {
	impl: _RW_Mutex,
}
 

A RW_Mutex is a reader/writer mutual exclusion lock The lock can be held by any arbitrary number of readers or a single writer The zero value for a RW_Mutex is an unlocked mutex

A RW_Mutex must not be copied after first use

Recursive_Benaphore ¶

Recursive_Benaphore :: struct {
	counter:   int,
	owner:     int,
	recursion: i32,
	sema:      Sema,
}

Recursive_Mutex ¶

Recursive_Mutex :: struct {
	impl: _Recursive_Mutex,
}
 

A Recursive_Mutex is a recursive mutual exclusion lock The zero value for a Recursive_Mutex is an unlocked mutex

A Recursive_Mutex must not be copied after first use

Sema ¶

Sema :: struct {
	impl: _Sema,
}
 

When waited upon, blocks until the internal count is greater than zero, then subtracts one. Posting to the semaphore increases the count by one, or the provided amount.

A Sema must not be copied after first use

Ticket_Mutex ¶

Ticket_Mutex :: struct {
	ticket:  uint,
	serving: uint,
}

Wait_Group ¶

Wait_Group :: struct {
	counter: int,
	mutex:   Mutex,
	cond:    Cond,
}
 

A Wait_Group waits for a collection of threads to finish

A Wait_Group must not be copied after first use

Constants

Atomic_RW_Mutex_State_Half_Width ¶

Atomic_RW_Mutex_State_Half_Width :: size_of(Atomic_RW_Mutex_State) * 8 / 2

Atomic_RW_Mutex_State_Is_Writing ¶

Atomic_RW_Mutex_State_Is_Writing :: Atomic_RW_Mutex_State(1)

Atomic_RW_Mutex_State_Reader ¶

Atomic_RW_Mutex_State_Reader :: Atomic_RW_Mutex_State(1) << Atomic_RW_Mutex_State_Half_Width

Atomic_RW_Mutex_State_Reader_Mask ¶

Atomic_RW_Mutex_State_Reader_Mask :: Atomic_RW_Mutex_State(1 << (Atomic_RW_Mutex_State_Half_Width - 1) - 1) << Atomic_RW_Mutex_State_Half_Width

Atomic_RW_Mutex_State_Writer ¶

Atomic_RW_Mutex_State_Writer :: Atomic_RW_Mutex_State(1) << 1

Atomic_RW_Mutex_State_Writer_Mask ¶

Atomic_RW_Mutex_State_Writer_Mask :: Atomic_RW_Mutex_State(1 << (Atomic_RW_Mutex_State_Half_Width - 1) - 1) << 1

Variables

This section is empty.

Procedures

atomic_add ¶

atomic_add :: intrinsics.atomic_add

atomic_add_explicit ¶

atomic_add_explicit :: intrinsics.atomic_add_explicit

atomic_and ¶

atomic_and :: intrinsics.atomic_and

atomic_and_explicit ¶

atomic_and_explicit :: intrinsics.atomic_and_explicit

atomic_compare_exchange_strong ¶

atomic_compare_exchange_strong :: intrinsics.atomic_compare_exchange_strong
 

Returns value and optional ok boolean

atomic_compare_exchange_strong_explicit ¶

atomic_compare_exchange_strong_explicit :: intrinsics.atomic_compare_exchange_strong_explicit

atomic_compare_exchange_weak ¶

atomic_compare_exchange_weak :: intrinsics.atomic_compare_exchange_weak

atomic_compare_exchange_weak_explicit ¶

atomic_compare_exchange_weak_explicit :: intrinsics.atomic_compare_exchange_weak_explicit

atomic_cond_broadcast ¶

atomic_cond_broadcast :: proc "odin" (c: ^Atomic_Cond) {…}

atomic_cond_signal ¶

atomic_cond_signal :: proc "odin" (c: ^Atomic_Cond) {…}

atomic_cond_wait ¶

atomic_cond_wait :: proc "odin" (c: ^Atomic_Cond, m: ^Atomic_Mutex) {…}

atomic_cond_wait_with_timeout ¶

atomic_cond_wait_with_timeout :: proc "odin" (c: ^Atomic_Cond, m: ^Atomic_Mutex, duration: time.Duration) -> (ok: bool) {…}

atomic_exchange ¶

atomic_exchange :: intrinsics.atomic_exchange

atomic_exchange_explicit ¶

atomic_exchange_explicit :: intrinsics.atomic_exchange_explicit

atomic_load ¶

atomic_load :: intrinsics.atomic_load

atomic_load_explicit ¶

atomic_load_explicit :: intrinsics.atomic_load_explicit

atomic_mutex_guard ¶

atomic_mutex_guard :: proc "odin" (m: ^Atomic_Mutex) -> bool {…}

atomic_mutex_lock ¶

atomic_mutex_lock :: proc "odin" (m: ^Atomic_Mutex) {…}
 

atomic_mutex_lock locks m

atomic_mutex_try_lock ¶

atomic_mutex_try_lock :: proc "odin" (m: ^Atomic_Mutex) -> bool {…}
 

atomic_mutex_try_lock tries to lock m, will return true on success, and false on failure

atomic_mutex_unlock ¶

atomic_mutex_unlock :: proc "odin" (m: ^Atomic_Mutex) {…}
 

atomic_mutex_unlock unlocks m

atomic_nand ¶

atomic_nand :: intrinsics.atomic_nand

atomic_nand_explicit ¶

atomic_nand_explicit :: intrinsics.atomic_nand_explicit

atomic_or ¶

atomic_or :: intrinsics.atomic_or

atomic_or_explicit ¶

atomic_or_explicit :: intrinsics.atomic_or_explicit

atomic_recursive_mutex_guard ¶

atomic_recursive_mutex_guard :: proc "odin" (m: ^Atomic_Recursive_Mutex) -> bool {…}

atomic_recursive_mutex_lock ¶

atomic_recursive_mutex_lock :: proc "odin" (m: ^Atomic_Recursive_Mutex) {…}

atomic_recursive_mutex_try_lock ¶

atomic_recursive_mutex_try_lock :: proc "odin" (m: ^Atomic_Recursive_Mutex) -> bool {…}

atomic_recursive_mutex_unlock ¶

atomic_recursive_mutex_unlock :: proc "odin" (m: ^Atomic_Recursive_Mutex) {…}

atomic_rw_mutex_guard ¶

atomic_rw_mutex_guard :: proc "odin" (rw: ^Atomic_RW_Mutex) -> bool {…}

atomic_rw_mutex_lock ¶

atomic_rw_mutex_lock :: proc "odin" (rw: ^Atomic_RW_Mutex) {…}
 

atomic_rw_mutex_lock locks rw for writing (with a single writer) If the mutex is already locked for reading or writing, the mutex blocks until the mutex is available.

atomic_rw_mutex_shared_guard ¶

atomic_rw_mutex_shared_guard :: proc "odin" (rw: ^Atomic_RW_Mutex) -> bool {…}

atomic_rw_mutex_shared_lock ¶

atomic_rw_mutex_shared_lock :: proc "odin" (rw: ^Atomic_RW_Mutex) {…}
 

atomic_rw_mutex_shared_lock locks rw for reading (with arbitrary number of readers)

atomic_rw_mutex_shared_unlock ¶

atomic_rw_mutex_shared_unlock :: proc "odin" (rw: ^Atomic_RW_Mutex) {…}
 

atomic_rw_mutex_shared_unlock unlocks rw for reading (with arbitrary number of readers)

atomic_rw_mutex_try_lock ¶

atomic_rw_mutex_try_lock :: proc "odin" (rw: ^Atomic_RW_Mutex) -> bool {…}
 

atomic_rw_mutex_try_lock tries to lock rw for writing (with a single writer)

atomic_rw_mutex_try_shared_lock ¶

atomic_rw_mutex_try_shared_lock :: proc "odin" (rw: ^Atomic_RW_Mutex) -> bool {…}
 

atomic_rw_mutex_try_shared_lock tries to lock rw for reading (with arbitrary number of readers)

atomic_rw_mutex_unlock ¶

atomic_rw_mutex_unlock :: proc "odin" (rw: ^Atomic_RW_Mutex) {…}
 

atomic_rw_mutex_unlock unlocks rw for writing (with a single writer)

atomic_sema_post ¶

atomic_sema_post :: proc "odin" (s: ^Atomic_Sema, count: int = 1) {…}

atomic_sema_wait ¶

atomic_sema_wait :: proc "odin" (s: ^Atomic_Sema) {…}

atomic_sema_wait_with_timeout ¶

atomic_sema_wait_with_timeout :: proc "odin" (s: ^Atomic_Sema, duration: time.Duration) -> bool {…}

atomic_signal_fence ¶

atomic_signal_fence :: intrinsics.atomic_signal_fence

atomic_store ¶

atomic_store :: intrinsics.atomic_store

atomic_store_explicit ¶

atomic_store_explicit :: intrinsics.atomic_store_explicit

atomic_sub ¶

atomic_sub :: intrinsics.atomic_sub

atomic_sub_explicit ¶

atomic_sub_explicit :: intrinsics.atomic_sub_explicit

atomic_thread_fence ¶

atomic_thread_fence :: intrinsics.atomic_thread_fence

atomic_xor ¶

atomic_xor :: intrinsics.atomic_xor

atomic_xor_explicit ¶

atomic_xor_explicit :: intrinsics.atomic_xor_explicit

auto_reset_event_signal ¶

auto_reset_event_signal :: proc "odin" (e: ^Auto_Reset_Event) {…}

auto_reset_event_wait ¶

auto_reset_event_wait :: proc "odin" (e: ^Auto_Reset_Event) {…}

barrier_init ¶

barrier_init :: proc "odin" (b: ^Barrier, thread_count: int) {…}

barrier_wait ¶

barrier_wait :: proc "odin" (b: ^Barrier) -> (is_leader: bool) {…}
 

Block the current thread until all threads have rendezvoused Barrier can be reused after all threads rendezvoused once, and can be used continuously

benaphore_guard ¶

benaphore_guard :: proc "odin" (b: ^Benaphore) -> bool {…}

benaphore_lock ¶

benaphore_lock :: proc "odin" (b: ^Benaphore) {…}

benaphore_try_lock ¶

benaphore_try_lock :: proc "odin" (b: ^Benaphore) -> bool {…}

benaphore_unlock ¶

benaphore_unlock :: proc "odin" (b: ^Benaphore) {…}

cond_broadcast ¶

cond_broadcast :: proc "odin" (c: ^Cond) {…}

cond_signal ¶

cond_signal :: proc "odin" (c: ^Cond) {…}

cond_wait ¶

cond_wait :: proc "odin" (c: ^Cond, m: ^Mutex) {…}

cond_wait_with_timeout ¶

cond_wait_with_timeout :: proc "odin" (c: ^Cond, m: ^Mutex, duration: time.Duration) -> bool {…}

cpu_relax ¶

cpu_relax :: intrinsics.cpu_relax

current_thread_id ¶

current_thread_id :: proc "contextless" () -> int {…}

futex_broadcast ¶

futex_broadcast :: proc "odin" (f: ^Futex) {…}

futex_signal ¶

futex_signal :: proc "odin" (f: ^Futex) {…}

futex_wait ¶

futex_wait :: proc "odin" (f: ^Futex, expected: u32) {…}

futex_wait_with_timeout ¶

futex_wait_with_timeout :: proc "odin" (f: ^Futex, expected: u32, duration: time.Duration) -> bool {…}
 

returns true if the wait happened within the duration, false if it exceeded the time duration

mutex_guard ¶

mutex_guard :: proc "odin" (m: ^Mutex) -> bool {…}

mutex_lock ¶

mutex_lock :: proc "odin" (m: ^Mutex) {…}
 

mutex_lock locks m

mutex_try_lock ¶

mutex_try_lock :: proc "odin" (m: ^Mutex) -> bool {…}
 

mutex_try_lock tries to lock m, will return true on success, and false on failure

mutex_unlock ¶

mutex_unlock :: proc "odin" (m: ^Mutex) {…}
 

mutex_unlock unlocks m

once_do ¶

once_do :: proc "odin" (o: ^Once, fn: proc "odin" ()) {…}
 

once_do calls the procedure fn if and only if once_do is being called for the first for this instance of Once.

park ¶

park :: proc "odin" (p: ^Parker) {…}
 

Blocks the current thread until the token is made available.

Assumes this is only called by the thread that owns the Parker.

park_with_timeout ¶

park_with_timeout :: proc "odin" (p: ^Parker, duration: time.Duration) {…}
 

Blocks the current thread until the token is made available, but only for a limited duration.

Assumes this is only called by the thread that owns the Parker

recursive_benaphore_guard ¶

recursive_benaphore_guard :: proc "odin" (b: ^Recursive_Benaphore) -> bool {…}

recursive_benaphore_lock ¶

recursive_benaphore_lock :: proc "odin" (b: ^Recursive_Benaphore) {…}

recursive_benaphore_try_lock ¶

recursive_benaphore_try_lock :: proc "odin" (b: ^Recursive_Benaphore) -> bool {…}

recursive_benaphore_unlock ¶

recursive_benaphore_unlock :: proc "odin" (b: ^Recursive_Benaphore) {…}

recursive_mutex_guard ¶

recursive_mutex_guard :: proc "odin" (m: ^Recursive_Mutex) -> bool {…}

recursive_mutex_lock ¶

recursive_mutex_lock :: proc "odin" (m: ^Recursive_Mutex) {…}

recursive_mutex_try_lock ¶

recursive_mutex_try_lock :: proc "odin" (m: ^Recursive_Mutex) -> bool {…}

recursive_mutex_unlock ¶

recursive_mutex_unlock :: proc "odin" (m: ^Recursive_Mutex) {…}

rw_mutex_guard ¶

rw_mutex_guard :: proc "odin" (rw: ^RW_Mutex) -> bool {…}

rw_mutex_lock ¶

rw_mutex_lock :: proc "odin" (rw: ^RW_Mutex) {…}
 

rw_mutex_lock locks rw for writing (with a single writer) If the mutex is already locked for reading or writing, the mutex blocks until the mutex is available.

rw_mutex_shared_guard ¶

rw_mutex_shared_guard :: proc "odin" (rw: ^RW_Mutex) -> bool {…}

rw_mutex_shared_lock ¶

rw_mutex_shared_lock :: proc "odin" (rw: ^RW_Mutex) {…}
 

rw_mutex_shared_lock locks rw for reading (with arbitrary number of readers)

rw_mutex_shared_unlock ¶

rw_mutex_shared_unlock :: proc "odin" (rw: ^RW_Mutex) {…}
 

rw_mutex_shared_unlock unlocks rw for reading (with arbitrary number of readers)

rw_mutex_try_lock ¶

rw_mutex_try_lock :: proc "odin" (rw: ^RW_Mutex) -> bool {…}
 

rw_mutex_try_lock tries to lock rw for writing (with a single writer)

rw_mutex_try_shared_lock ¶

rw_mutex_try_shared_lock :: proc "odin" (rw: ^RW_Mutex) -> bool {…}
 

rw_mutex_try_shared_lock tries to lock rw for reading (with arbitrary number of readers)

rw_mutex_unlock ¶

rw_mutex_unlock :: proc "odin" (rw: ^RW_Mutex) {…}
 

rw_mutex_unlock unlocks rw for writing (with a single writer)

sema_post ¶

sema_post :: proc "odin" (s: ^Sema, count: int = 1) {…}

sema_wait ¶

sema_wait :: proc "odin" (s: ^Sema) {…}

sema_wait_with_timeout ¶

sema_wait_with_timeout :: proc "odin" (s: ^Sema, duration: time.Duration) -> bool {…}

ticket_mutex_guard ¶

ticket_mutex_guard :: proc "odin" (m: ^Ticket_Mutex) -> bool {…}

ticket_mutex_lock ¶

ticket_mutex_lock :: proc "odin" (m: ^Ticket_Mutex) {…}

ticket_mutex_unlock ¶

ticket_mutex_unlock :: proc "odin" (m: ^Ticket_Mutex) {…}

unpark ¶

unpark :: proc "odin" (p: ^Parker) {…}
 

Automatically makes thee token available if it was not already.

wait_group_add ¶

wait_group_add :: proc "odin" (wg: ^Wait_Group, delta: int) {…}

wait_group_done ¶

wait_group_done :: proc "odin" (wg: ^Wait_Group) {…}

wait_group_wait ¶

wait_group_wait :: proc "odin" (wg: ^Wait_Group) {…}

wait_group_wait_with_timeout ¶

wait_group_wait_with_timeout :: proc "odin" (wg: ^Wait_Group, duration: time.Duration) -> bool {…}

Procedure Groups

shared_guard ¶

 

Example:
if shared_guard(&m) {
	...
}

shared_lock ¶

 

shared_lock locks rw for reading (with arbitrary number of readers)

shared_unlock ¶

 

shared_unlock unlocks rw for reading (with arbitrary number of readers)

try_lock ¶

 

try_lock tries to lock m, will return true on success, and false on failure

try_shared_lock ¶

 

try_shared_lock tries to lock rw for reading (with arbitrary number of readers)

Source Files

Generation Information

Generated with odin version dev-2022-10 (vendor "odin") Windows_amd64 @ 2022-10-05 21:11:47.523670600 +0000 UTC