thread.create et al with name parameter

This commit is contained in:
PePerRoNii
2025-07-22 10:52:29 +07:00
parent 8d278acba5
commit a357113651
4 changed files with 53 additions and 64 deletions

View File

@@ -48,6 +48,9 @@ Thread :: struct {
// started. Should be set after the thread has been created, but before
// it is started.
data: rawptr,
// Thread's Name/Description that will get set during thread creation
// for thread's creation only : do not refer to it, use thread.get_name instead
name: Maybe(string),
// User-supplied integer, that will be available to the thread once it is
// started. Should be set after the thread has been created, but before
// it is started.
@@ -102,8 +105,8 @@ thread will be in a suspended state, until `start()` procedure is called.
To start the thread, call `start()`. Also the `create_and_start()`
procedure can be called to create and start the thread immediately.
*/
create :: proc(procedure: Thread_Proc, priority := Thread_Priority.Normal) -> ^Thread {
return _create(procedure, priority)
create :: proc(procedure: Thread_Proc, priority := Thread_Priority.Normal, name: Maybe(string) = nil) -> ^Thread {
return _create(procedure, priority, name)
}
/*
@@ -166,20 +169,6 @@ get_name :: proc(thread: ^Thread, allocator := context.temp_allocator, loc := #c
return _get_name(thread, allocator, loc)
}
/*
Set thread's name/description.
If thread is nil the procedure will set the name of the calling thread.
the provided string must be available until this procedure ends
and will be truncated to fit their platform's limit.
MacOS: only supports changing the name of the calling thread.
if thread is not nil the procedure will do nothing.
*/
set_name :: proc(thread: ^Thread, name: string) {
_set_name(thread, name)
}
/*
Run a procedure on a different thread.
@@ -191,8 +180,8 @@ to execute. The thread will have priority specified by the `priority` parameter.
is used, the thread procedure needs to call `runtime.default_temp_allocator_destroy()`
in order to free the resources associated with the temporary allocations.
*/
run :: proc(fn: proc(), init_context: Maybe(runtime.Context) = nil, priority := Thread_Priority.Normal) {
create_and_start(fn, init_context, priority, true)
run :: proc(fn: proc(), init_context: Maybe(runtime.Context) = nil, priority := Thread_Priority.Normal, name: Maybe(string) = nil) {
create_and_start(fn, init_context, priority, true, name)
}
/*
@@ -206,8 +195,8 @@ to execute. The thread will have priority specified by the `priority` parameter.
is used, the thread procedure needs to call `runtime.default_temp_allocator_destroy()`
in order to free the resources associated with the temporary allocations.
*/
run_with_data :: proc(data: rawptr, fn: proc(data: rawptr), init_context: Maybe(runtime.Context) = nil, priority := Thread_Priority.Normal) {
create_and_start_with_data(data, fn, init_context, priority, true)
run_with_data :: proc(data: rawptr, fn: proc(data: rawptr), init_context: Maybe(runtime.Context) = nil, priority := Thread_Priority.Normal, name: Maybe(string) = nil) {
create_and_start_with_data(data, fn, init_context, priority, true, name)
}
/*
@@ -221,9 +210,9 @@ to execute. The thread will have priority specified by the `priority` parameter.
is used, the thread procedure needs to call `runtime.default_temp_allocator_destroy()`
in order to free the resources associated with the temporary allocations.
*/
run_with_poly_data :: proc(data: $T, fn: proc(data: T), init_context: Maybe(runtime.Context) = nil, priority := Thread_Priority.Normal)
run_with_poly_data :: proc(data: $T, fn: proc(data: T), init_context: Maybe(runtime.Context) = nil, priority := Thread_Priority.Normal, name: Maybe(string) = nil)
where size_of(T) <= size_of(rawptr) * MAX_USER_ARGUMENTS {
create_and_start_with_poly_data(data, fn, init_context, priority, true)
create_and_start_with_poly_data(data, fn, init_context, priority, true, name)
}
/*
@@ -237,9 +226,9 @@ to execute. The thread will have priority specified by the `priority` parameter.
is used, the thread procedure needs to call `runtime.default_temp_allocator_destroy()`
in order to free the resources associated with the temporary allocations.
*/
run_with_poly_data2 :: proc(arg1: $T1, arg2: $T2, fn: proc(T1, T2), init_context: Maybe(runtime.Context) = nil, priority := Thread_Priority.Normal)
run_with_poly_data2 :: proc(arg1: $T1, arg2: $T2, fn: proc(T1, T2), init_context: Maybe(runtime.Context) = nil, priority := Thread_Priority.Normal, name: Maybe(string) = nil)
where size_of(T1) + size_of(T2) <= size_of(rawptr) * MAX_USER_ARGUMENTS {
create_and_start_with_poly_data2(arg1, arg2, fn, init_context, priority, true)
create_and_start_with_poly_data2(arg1, arg2, fn, init_context, priority, true, name)
}
/*
@@ -253,9 +242,9 @@ to execute. The thread will have priority specified by the `priority` parameter.
is used, the thread procedure needs to call `runtime.default_temp_allocator_destroy()`
in order to free the resources associated with the temporary allocations.
*/
run_with_poly_data3 :: proc(arg1: $T1, arg2: $T2, arg3: $T3, fn: proc(arg1: T1, arg2: T2, arg3: T3), init_context: Maybe(runtime.Context) = nil, priority := Thread_Priority.Normal)
run_with_poly_data3 :: proc(arg1: $T1, arg2: $T2, arg3: $T3, fn: proc(arg1: T1, arg2: T2, arg3: T3), init_context: Maybe(runtime.Context) = nil, priority := Thread_Priority.Normal, name: Maybe(string) = nil)
where size_of(T1) + size_of(T2) + size_of(T3) <= size_of(rawptr) * MAX_USER_ARGUMENTS {
create_and_start_with_poly_data3(arg1, arg2, arg3, fn, init_context, priority, true)
create_and_start_with_poly_data3(arg1, arg2, arg3, fn, init_context, priority, true, name)
}
/*
@@ -269,9 +258,9 @@ to execute. The thread will have priority specified by the `priority` parameter.
is used, the thread procedure needs to call `runtime.default_temp_allocator_destroy()`
in order to free the resources associated with the temporary allocations.
*/
run_with_poly_data4 :: proc(arg1: $T1, arg2: $T2, arg3: $T3, arg4: $T4, fn: proc(arg1: T1, arg2: T2, arg3: T3, arg4: T4), init_context: Maybe(runtime.Context) = nil, priority := Thread_Priority.Normal)
run_with_poly_data4 :: proc(arg1: $T1, arg2: $T2, arg3: $T3, arg4: $T4, fn: proc(arg1: T1, arg2: T2, arg3: T3, arg4: T4), init_context: Maybe(runtime.Context) = nil, priority := Thread_Priority.Normal, name: Maybe(string) = nil)
where size_of(T1) + size_of(T2) + size_of(T3) + size_of(T4) <= size_of(rawptr) * MAX_USER_ARGUMENTS {
create_and_start_with_poly_data4(arg1, arg2, arg3, arg4, fn, init_context, priority, true)
create_and_start_with_poly_data4(arg1, arg2, arg3, arg4, fn, init_context, priority, true, name)
}
/*
@@ -292,12 +281,12 @@ That includes calling `join`, which needs to dereference ^Thread`.
is used, the thread procedure needs to call `runtime.default_temp_allocator_destroy()`
in order to free the resources associated with the temporary allocations.
*/
create_and_start :: proc(fn: proc(), init_context: Maybe(runtime.Context) = nil, priority := Thread_Priority.Normal, self_cleanup := false) -> (t: ^Thread) {
create_and_start :: proc(fn: proc(), init_context: Maybe(runtime.Context) = nil, priority := Thread_Priority.Normal, self_cleanup := false, name: Maybe(string) = nil) -> (t: ^Thread) {
thread_proc :: proc(t: ^Thread) {
fn := cast(proc())t.data
fn()
}
if t = create(thread_proc, priority); t == nil {
if t = create(thread_proc, priority, name); t == nil {
return
}
t.data = rawptr(fn)
@@ -327,14 +316,14 @@ That includes calling `join`, which needs to dereference ^Thread`.
is used, the thread procedure needs to call `runtime.default_temp_allocator_destroy()`
in order to free the resources associated with the temporary allocations.
*/
create_and_start_with_data :: proc(data: rawptr, fn: proc(data: rawptr), init_context: Maybe(runtime.Context) = nil, priority := Thread_Priority.Normal, self_cleanup := false) -> (t: ^Thread) {
create_and_start_with_data :: proc(data: rawptr, fn: proc(data: rawptr), init_context: Maybe(runtime.Context) = nil, priority := Thread_Priority.Normal, self_cleanup := false, name: Maybe(string) = nil) -> (t: ^Thread) {
thread_proc :: proc(t: ^Thread) {
fn := cast(proc(rawptr))t.data
assert(t.user_index >= 1)
data := t.user_args[0]
fn(data)
}
if t = create(thread_proc, priority); t == nil {
if t = create(thread_proc, priority, name); t == nil {
return
}
t.data = rawptr(fn)
@@ -366,7 +355,7 @@ That includes calling `join`, which needs to dereference ^Thread`.
is used, the thread procedure needs to call `runtime.default_temp_allocator_destroy()`
in order to free the resources associated with the temporary allocations.
*/
create_and_start_with_poly_data :: proc(data: $T, fn: proc(data: T), init_context: Maybe(runtime.Context) = nil, priority := Thread_Priority.Normal, self_cleanup := false) -> (t: ^Thread)
create_and_start_with_poly_data :: proc(data: $T, fn: proc(data: T), init_context: Maybe(runtime.Context) = nil, priority := Thread_Priority.Normal, self_cleanup := false, name: Maybe(string) = nil) -> (t: ^Thread)
where size_of(T) <= size_of(rawptr) * MAX_USER_ARGUMENTS {
thread_proc :: proc(t: ^Thread) {
fn := cast(proc(T))t.data
@@ -374,7 +363,7 @@ create_and_start_with_poly_data :: proc(data: $T, fn: proc(data: T), init_contex
data := (^T)(&t.user_args[0])^
fn(data)
}
if t = create(thread_proc, priority); t == nil {
if t = create(thread_proc, priority, name); t == nil {
return
}
t.data = rawptr(fn)
@@ -411,7 +400,7 @@ That includes calling `join`, which needs to dereference ^Thread`.
is used, the thread procedure needs to call `runtime.default_temp_allocator_destroy()`
in order to free the resources associated with the temporary allocations.
*/
create_and_start_with_poly_data2 :: proc(arg1: $T1, arg2: $T2, fn: proc(T1, T2), init_context: Maybe(runtime.Context) = nil, priority := Thread_Priority.Normal, self_cleanup := false) -> (t: ^Thread)
create_and_start_with_poly_data2 :: proc(arg1: $T1, arg2: $T2, fn: proc(T1, T2), init_context: Maybe(runtime.Context) = nil, priority := Thread_Priority.Normal, self_cleanup := false, name: Maybe(string) = nil) -> (t: ^Thread)
where size_of(T1) + size_of(T2) <= size_of(rawptr) * MAX_USER_ARGUMENTS {
thread_proc :: proc(t: ^Thread) {
fn := cast(proc(T1, T2))t.data
@@ -423,7 +412,7 @@ create_and_start_with_poly_data2 :: proc(arg1: $T1, arg2: $T2, fn: proc(T1, T2),
fn(arg1, arg2)
}
if t = create(thread_proc, priority); t == nil {
if t = create(thread_proc, priority, name); t == nil {
return
}
t.data = rawptr(fn)
@@ -462,7 +451,7 @@ That includes calling `join`, which needs to dereference ^Thread`.
is used, the thread procedure needs to call `runtime.default_temp_allocator_destroy()`
in order to free the resources associated with the temporary allocations.
*/
create_and_start_with_poly_data3 :: proc(arg1: $T1, arg2: $T2, arg3: $T3, fn: proc(arg1: T1, arg2: T2, arg3: T3), init_context: Maybe(runtime.Context) = nil, priority := Thread_Priority.Normal, self_cleanup := false) -> (t: ^Thread)
create_and_start_with_poly_data3 :: proc(arg1: $T1, arg2: $T2, arg3: $T3, fn: proc(arg1: T1, arg2: T2, arg3: T3), init_context: Maybe(runtime.Context) = nil, priority := Thread_Priority.Normal, self_cleanup := false, name: Maybe(string) = nil) -> (t: ^Thread)
where size_of(T1) + size_of(T2) + size_of(T3) <= size_of(rawptr) * MAX_USER_ARGUMENTS {
thread_proc :: proc(t: ^Thread) {
fn := cast(proc(T1, T2, T3))t.data
@@ -475,7 +464,7 @@ create_and_start_with_poly_data3 :: proc(arg1: $T1, arg2: $T2, arg3: $T3, fn: pr
fn(arg1, arg2, arg3)
}
if t = create(thread_proc, priority); t == nil {
if t = create(thread_proc, priority, name); t == nil {
return
}
t.data = rawptr(fn)
@@ -515,7 +504,7 @@ That includes calling `join`, which needs to dereference ^Thread`.
is used, the thread procedure needs to call `runtime.default_temp_allocator_destroy()`
in order to free the resources associated with the temporary allocations.
*/
create_and_start_with_poly_data4 :: proc(arg1: $T1, arg2: $T2, arg3: $T3, arg4: $T4, fn: proc(arg1: T1, arg2: T2, arg3: T3, arg4: T4), init_context: Maybe(runtime.Context) = nil, priority := Thread_Priority.Normal, self_cleanup := false) -> (t: ^Thread)
create_and_start_with_poly_data4 :: proc(arg1: $T1, arg2: $T2, arg3: $T3, arg4: $T4, fn: proc(arg1: T1, arg2: T2, arg3: T3, arg4: T4), init_context: Maybe(runtime.Context) = nil, priority := Thread_Priority.Normal, self_cleanup := false, name: Maybe(string) = nil) -> (t: ^Thread)
where size_of(T1) + size_of(T2) + size_of(T3) + size_of(T4) <= size_of(rawptr) * MAX_USER_ARGUMENTS {
thread_proc :: proc(t: ^Thread) {
fn := cast(proc(T1, T2, T3, T4))t.data
@@ -529,7 +518,7 @@ create_and_start_with_poly_data4 :: proc(arg1: $T1, arg2: $T2, arg3: $T3, arg4:
fn(arg1, arg2, arg3, arg4)
}
if t = create(thread_proc, priority); t == nil {
if t = create(thread_proc, priority, name); t == nil {
return
}
t.data = rawptr(fn)

View File

@@ -14,7 +14,7 @@ _thread_priority_map := [Thread_Priority]i32{
.High = +2,
}
_create :: proc(procedure: Thread_Proc, priority := Thread_Priority.Normal) -> ^Thread {
_create :: proc(procedure: Thread_Proc, priority := Thread_Priority.Normal, name: Maybe(string) = nil) -> ^Thread {
unimplemented("core:thread procedure not supported on target")
}

View File

@@ -19,7 +19,7 @@ Thread_Os_Specific :: struct #align(16) {
// Creates a thread which will run the given procedure.
// It then waits for `start` to be called.
//
_create :: proc(procedure: Thread_Proc, priority: Thread_Priority) -> ^Thread {
_create :: proc(procedure: Thread_Proc, priority: Thread_Priority, name: Maybe(string)) -> ^Thread {
__unix_thread_entry_proc :: proc "c" (t: rawptr) -> rawptr {
t := (^Thread)(t)
@@ -58,6 +58,8 @@ _create :: proc(procedure: Thread_Proc, priority: Thread_Priority) -> ^Thread {
runtime.run_thread_local_cleaners()
}
_set_name(t)
t.procedure(t)
}
@@ -211,23 +213,18 @@ _get_name :: proc(thread: ^Thread, allocator: runtime.Allocator, loc: runtime.So
return
}
_set_name :: proc(thread: ^Thread, name: string) {
// Haiku doesn't have pthread_getname yet
when ODIN_OS == .Haiku {
unimplemented("core:thread set_name for haiku is not yet supported")
} else when ODIN_OS == .Darwin {
if thread != nil {
return
}
} else {
tid: posix.pthread_t
if thread == nil {
tid = posix.pthread_self()
} else {
tid = thread.unix_thread
}
_set_name :: proc(thread: ^Thread) {
if ODIN_OS == .Haiku {
return
}
name, ok := thread.name.?
if !ok {
return
}
tid := thread.unix_thread
buf: [_MAX_PTHREAD_NAME_LENGTH]u8
copy(buf[:], name)

View File

@@ -25,7 +25,7 @@ _thread_priority_map := [Thread_Priority]i32{
.High = +2,
}
_create :: proc(procedure: Thread_Proc, priority: Thread_Priority) -> ^Thread {
_create :: proc(procedure: Thread_Proc, priority: Thread_Priority, name: Maybe(string)) -> ^Thread {
win32_thread_id: win32.DWORD
__windows_thread_entry_proc :: proc "system" (t_: rawptr) -> win32.DWORD {
@@ -47,6 +47,8 @@ _create :: proc(procedure: Thread_Proc, priority: Thread_Priority) -> ^Thread {
runtime.run_thread_local_cleaners()
}
_set_name(t)
t.procedure(t)
}
@@ -79,6 +81,7 @@ _create :: proc(procedure: Thread_Proc, priority: Thread_Priority) -> ^Thread {
thread.win32_thread = win32_thread
thread.win32_thread_id = win32_thread_id
thread.id = int(win32_thread_id)
thread.name = name
ok := win32.SetThreadPriority(win32_thread, _thread_priority_map[priority])
assert(ok == true)
@@ -170,14 +173,14 @@ _get_name :: proc(thread: ^Thread, allocator: runtime.Allocator, loc: runtime.So
return
}
_set_name :: proc(thread: ^Thread, name: string) {
t_handle: win32.HANDLE
if thread == nil {
t_handle = win32.GetCurrentThread()
} else {
t_handle = thread.win32_thread
_set_name :: proc(thread: ^Thread) {
name, ok := thread.name.?
if !ok {
return
}
t_handle = thread.win32_thread
buf: [_THREAD_DESCRIPTION_LENGTH]u16
// _THREAD_DESCRIPTION_LENGTH includes terminating null
utf16.encode_string(buf[:len(buf) - 1], name)