package core:thread

⌘K
Ctrl+K
or
/

    Types

    Pool ¶

    Pool :: struct {
    	allocator:         runtime.Allocator,
    	mutex:             sync.Mutex,
    	sem_available:     sync.Sema,
    	// the following values are atomic
    	num_waiting:       int,
    	num_in_processing: int,
    	num_outstanding:   int,
    	// num_waiting + num_in_processing
    	num_done:          int,
    	is_running:        bool,
    	threads:           []^Thread,
    	tasks:             [dynamic]Task,
    	tasks_done:        [dynamic]Task,
    }
     

    Do not access the pool's members directly while the pool threads are running, since they use different kinds of locking and mutual exclusion devices. Careless access can and will lead to nasty bugs. Once initialized, the pool's memory address is not allowed to change until it is destroyed.

    Related Procedures With Parameters

    Pool_Thread_Data ¶

    Pool_Thread_Data :: struct {
    	pool: ^Pool,
    	task: Task,
    }

    Task ¶

    Task :: struct {
    	procedure:  Task_Proc,
    	data:       rawptr,
    	user_index: int,
    	allocator:  runtime.Allocator,
    }
    Related Procedures With Parameters
    Related Procedures With Returns

    Task_Proc ¶

    Task_Proc :: proc(task: Task)
    Related Procedures With Parameters

    Thread ¶

    Thread :: struct {
    	using specific:     Thread_Os_Specific,
    	flags:              bit_set[Thread_State; u8],
    	id:                 int,
    	procedure:          Thread_Proc,
    	// 		These are values that the user can set as they wish, after the thread has been created.
    	// 		This data is easily available to the thread proc.
    	// 
    	// 		These fields can be assigned to directly.
    	// 
    	// 		Should be set after the thread is created, but before it is started.
    	data:               rawptr,
    	user_index:         int,
    	user_args:          [8]rawptr,
    	// 		The context to be used as 'context' in the thread proc.
    	// 
    	// 		This field can be assigned to directly, after the thread has been created, but __before__ the thread has been started.
    	// 		This field must not be changed after the thread has started.
    	// 
    	// 		NOTE: If you __don't__ set this, the temp allocator will be managed for you;
    	// 		      If you __do__ set this, then you're expected to handle whatever allocators you set, yourself.
    	// 
    	// 		IMPORTANT:
    	// 		By default, the thread proc will get the same context as `main()` gets.
    	// 		In this situation, the thread will get a new temporary allocator which will be cleaned up when the thread dies.
    	// 		***This does NOT happen when you set `init_context`.***
    	// 		This means that if you set `init_context`, but still have the `temp_allocator` field set to the default temp allocator,
    	// 		then you'll need to call `runtime.default_temp_allocator_destroy(auto_cast the_thread.init_context.temp_allocator.data)` manually,
    	// 		in order to prevent any memory leaks.
    	// 		This call ***must*** be done ***in the thread proc*** because the default temporary allocator uses thread local state!
    	init_context:       runtime.Maybe($T),
    	creation_allocator: runtime.Allocator,
    }
    Related Procedures With Parameters
    Related Procedures With Returns

    Thread_Proc ¶

    Thread_Proc :: proc(_: ^Thread)
    Related Procedures With Parameters

    Thread_State ¶

    Thread_State :: enum u8 {
    	Started, 
    	Joined, 
    	Done, 
    	Self_Cleanup, 
    }

    Constants

    IS_SUPPORTED ¶

    IS_SUPPORTED :: _IS_SUPPORTED

    MAX_USER_ARGUMENTS ¶

    MAX_USER_ARGUMENTS :: 8

    Variables

    This section is empty.

    Procedures

    create ¶

    create :: proc(procedure: Thread_Proc, priority: Thread_Priority = Thread_Priority.Normal) -> ^Thread {…}
     

    Creates a thread in a suspended state with the given priority.

    To start the thread, call `thread.start()`.
    
    See `thread.create_and_start()`.
    

    create_and_start ¶

    create_and_start :: proc(fn: proc(), init_context: runtime.Maybe($T) = nil, priority: Thread_Priority = Thread_Priority.Normal, self_cleanup: bool = false) -> ^Thread {…}

    create_and_start_with_data ¶

    create_and_start_with_data :: proc(data: rawptr, fn: proc(data: rawptr), init_context: runtime.Maybe($T) = nil, priority: Thread_Priority = Thread_Priority.Normal, self_cleanup: bool = false) -> ^Thread {…}

    create_and_start_with_poly_data ¶

    create_and_start_with_poly_data :: proc(data: $T, fn: proc(data: ), init_context: runtime.Maybe($T) = nil, priority: Thread_Priority = Thread_Priority.Normal, self_cleanup: bool = false) -> ^Thread {…}

    create_and_start_with_poly_data2 ¶

    create_and_start_with_poly_data2 :: proc(
    	arg1:         $T, 
    	arg2:         $T, 
    	fn:           proc(_: , _: ), 
    	init_context: runtime.Maybe($T) = nil, 
    	priority:     Thread_Priority = Thread_Priority.Normal, 
    	self_cleanup: bool = false, 
    ) -> ^Thread {…}

    create_and_start_with_poly_data3 ¶

    create_and_start_with_poly_data3 :: proc(
    	arg1:         $T, 
    	arg2:         $T, 
    	arg3:         $T, 
    	fn:           proc(arg1: , arg2: , arg3: ), 
    	init_context: runtime.Maybe($T) = nil, 
    	priority:     Thread_Priority = Thread_Priority.Normal, 
    	self_cleanup: bool = false, 
    ) -> ^Thread {…}

    create_and_start_with_poly_data4 ¶

    create_and_start_with_poly_data4 :: proc(
    	arg1:         $T, 
    	arg2:         $T, 
    	arg3:         $T, 
    	arg4:         $T, 
    	fn:           proc(arg1: , arg2: , arg3: , arg4: ), 
    	init_context: runtime.Maybe($T) = nil, 
    	priority:     Thread_Priority = Thread_Priority.Normal, 
    	self_cleanup: bool = false, 
    ) -> ^Thread {…}

    destroy ¶

    destroy :: proc(thread: ^Thread) {…}

    is_done ¶

    is_done :: proc(thread: ^Thread) -> bool {…}

    join ¶

    join :: proc(thread: ^Thread) {…}

    join_multiple ¶

    join_multiple :: proc(.. threads: ..^Thread) {…}

    pool_add_task ¶

    pool_add_task :: proc(pool: ^Pool, allocator: runtime.Allocator, procedure: Task_Proc, data: rawptr, user_index: int = 0) {…}
     

    Add a task to the thread pool.

    Tasks can be added from any thread, not just the thread that created the thread pool. You can even add tasks from inside other tasks.

    Each task also needs an allocator which it either owns, or which is thread safe.

    pool_destroy ¶

    pool_destroy :: proc(pool: ^Pool) {…}

    pool_do_work ¶

    pool_do_work :: proc(pool: ^Pool, task: Task) {…}
     

    Mostly for internal use.

    pool_finish ¶

    pool_finish :: proc(pool: ^Pool) {…}
     

    Process the rest of the tasks, also use this thread for processing, then join all the pool threads.

    pool_init ¶

    pool_init :: proc(pool: ^Pool, allocator: runtime.Allocator, thread_count: int) {…}
     

    Once initialized, the pool's memory address is not allowed to change until it is destroyed.

    The thread pool requires an allocator which it either owns, or which is thread safe.

    pool_is_empty ¶

    pool_is_empty :: proc(pool: ^Pool) -> bool {…}
     

    If tasks are only being added from one thread, and this procedure is being called from that same thread, it will reliably tell if the thread pool is empty or not. Empty in this case means there are no tasks waiting, being processed, or _done_.

    pool_join ¶

    pool_join :: proc(pool: ^Pool) {…}
     

    Finish tasks that have already started processing, then shut down all pool threads. Might leave over waiting tasks, any memory allocated for the user data of those tasks will not be freed.

    pool_num_done ¶

    pool_num_done :: proc(pool: ^Pool) -> int {…}
     

    Number of tasks which are done processing. Only informational, mostly for debugging. Don't rely on this value being consistent with other num_* values.

    pool_num_in_processing ¶

    pool_num_in_processing :: proc(pool: ^Pool) -> int {…}
     

    Number of tasks currently being processed. Only informational, mostly for debugging. Don't rely on this value being consistent with other num_* values.

    pool_num_outstanding ¶

    pool_num_outstanding :: proc(pool: ^Pool) -> int {…}
     

    Outstanding tasks are all tasks that are not done, that is, tasks that are waiting, as well as tasks that are currently being processed. Only informational, mostly for debugging. Don't rely on this value being consistent with other num_* values.

    pool_num_waiting ¶

    pool_num_waiting :: proc(pool: ^Pool) -> int {…}
     

    Number of tasks waiting to be processed. Only informational, mostly for debugging. Don't rely on this value being consistent with other num_* values.

    pool_pop_done ¶

    pool_pop_done :: proc(pool: ^Pool) -> (task: Task, got_task: bool) {…}
     

    Use this to take out finished tasks.

    pool_pop_waiting ¶

    pool_pop_waiting :: proc(pool: ^Pool) -> (task: Task, got_task: bool) {…}
     

    Mostly for internal use.

    pool_shutdown ¶

    pool_shutdown :: proc(pool: ^Pool, exit_code: int = 1) {…}
     

    Force the pool to stop all of its threads and put it into a state where it will no longer run any more tasks.

    The pool must still be destroyed after this.

    pool_start ¶

    pool_start :: proc(pool: ^Pool) {…}

    pool_stop_all_tasks ¶

    pool_stop_all_tasks :: proc(pool: ^Pool, exit_code: int = 1) {…}
     

    Forcibly stop all running tasks.

    The same notes from pool_stop_task apply here.

    pool_stop_task ¶

    pool_stop_task :: proc(pool: ^Pool, user_index: int, exit_code: int = 1) -> bool {…}
     

    Forcibly stop a running task by its user index.

    This will terminate the underlying thread. Ideally, you should use some means of communication to stop a task, as thread termination may leave resources unclaimed.

    The thread will be restarted to accept new tasks.

    Returns true if the task was found and terminated.

    run ¶

    run :: proc(fn: proc(), init_context: runtime.Maybe($T) = nil, priority: Thread_Priority = Thread_Priority.Normal) {…}

    run_with_data ¶

    run_with_data :: proc(data: rawptr, fn: proc(data: rawptr), init_context: runtime.Maybe($T) = nil, priority: Thread_Priority = Thread_Priority.Normal) {…}

    run_with_poly_data ¶

    run_with_poly_data :: proc(data: $T, fn: proc(data: ), init_context: runtime.Maybe($T) = nil, priority: Thread_Priority = Thread_Priority.Normal) {…}

    run_with_poly_data2 ¶

    run_with_poly_data2 :: proc(arg1: $T, arg2: $T, fn: proc(_: , _: ), init_context: runtime.Maybe($T) = nil, priority: Thread_Priority = Thread_Priority.Normal) {…}

    run_with_poly_data3 ¶

    run_with_poly_data3 :: proc(
    	arg1:         $T, 
    	arg2:         $T, 
    	arg3:         $T, 
    	fn:           proc(arg1: , arg2: , arg3: ), 
    	init_context: runtime.Maybe($T) = nil, 
    	priority:     Thread_Priority = Thread_Priority.Normal, 
    ) {…}

    run_with_poly_data4 ¶

    run_with_poly_data4 :: proc(
    	arg1:         $T, 
    	arg2:         $T, 
    	arg3:         $T, 
    	arg4:         $T, 
    	fn:           proc(arg1: , arg2: , arg3: , arg4: ), 
    	init_context: runtime.Maybe($T) = nil, 
    	priority:     Thread_Priority = Thread_Priority.Normal, 
    ) {…}

    start ¶

    start :: proc(thread: ^Thread) {…}

    terminate ¶

    terminate :: proc(thread: ^Thread, exit_code: int) {…}

    yield ¶

    yield :: proc() {…}

    Procedure Groups

    This section is empty.

    Source Files

    Generation Information

    Generated with odin version dev-2024-07 (vendor "odin") Windows_amd64 @ 2024-07-18 21:09:42.968469800 +0000 UTC