mirror of
https://github.com/Ed94/Odin.git
synced 2026-08-05 15:18:49 +00:00
[thread] Refactor handling of 'init_context' + add doc comments for it
This commit is contained in:
@@ -14,10 +14,37 @@ Thread :: struct {
|
||||
using specific: Thread_Os_Specific,
|
||||
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: [MAX_USER_ARGUMENTS]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 sitation, 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: Maybe(runtime.Context),
|
||||
|
||||
|
||||
@@ -32,6 +59,12 @@ Thread_Priority :: enum {
|
||||
High,
|
||||
}
|
||||
|
||||
/*
|
||||
Creates a thread in a suspended state with the given priority.
|
||||
To start the thread, call `thread.start()`.
|
||||
|
||||
See `thread.create_and_start()`.
|
||||
*/
|
||||
create :: proc(procedure: Thread_Proc, priority := Thread_Priority.Normal) -> ^Thread {
|
||||
return _create(procedure, priority)
|
||||
}
|
||||
@@ -298,3 +331,33 @@ create_and_start_with_poly_data4 :: proc(arg1: $T1, arg2: $T2, arg3: $T3, arg4:
|
||||
start(t)
|
||||
return t
|
||||
}
|
||||
|
||||
|
||||
_select_context_for_thread :: proc(init_context: Maybe(runtime.Context)) -> runtime.Context {
|
||||
ctx, ok := init_context.?
|
||||
if !ok {
|
||||
return runtime.default_context()
|
||||
}
|
||||
|
||||
/*
|
||||
NOTE(tetra, 2023-05-31):
|
||||
Ensure that the temp allocator is thread-safe when the user provides a specific initial context to use.
|
||||
Without this, the thread will use the same temp allocator state as the parent thread, and thus, bork it up.
|
||||
*/
|
||||
if ctx.temp_allocator.procedure == runtime.default_temp_allocator_proc {
|
||||
ctx.temp_allocator.data = &runtime.global_default_temp_allocator_data
|
||||
}
|
||||
return ctx
|
||||
}
|
||||
|
||||
_maybe_destroy_default_temp_allocator :: proc(init_context: Maybe(runtime.Context)) {
|
||||
if init_context != nil {
|
||||
// NOTE(tetra, 2023-05-31): If the user specifies a custom context for the thread,
|
||||
// then it's entirely up to them to handle whatever allocators they're using.
|
||||
return
|
||||
}
|
||||
|
||||
if context.temp_allocator.procedure == runtime.default_temp_allocator_proc {
|
||||
runtime.default_temp_allocator_destroy(auto_cast context.temp_allocator.data)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user