diff options
| author | hikari <ftphikari@gmail.com> | 2023-06-07 19:11:16 +0300 |
|---|---|---|
| committer | hikari <ftphikari@gmail.com> | 2023-06-07 19:11:16 +0300 |
| commit | dcf4e51787119d8dcf86ca0195d3a07aea6d47a8 (patch) | |
| tree | 0b5cc5674de634e52d4a2fdbdbee1618007801da /core/thread/thread.odin | |
| parent | 7dc09ed4501d0a7b256a05e6467cd86a262367ae (diff) | |
[core:thread] Added `self_cleanup` flag to properly auto-clean threads
Diffstat (limited to 'core/thread/thread.odin')
| -rw-r--r-- | core/thread/thread.odin | 126 |
1 files changed, 27 insertions, 99 deletions
diff --git a/core/thread/thread.odin b/core/thread/thread.odin index fe502c5ae..c84317055 100644 --- a/core/thread/thread.odin +++ b/core/thread/thread.odin @@ -38,7 +38,7 @@ Thread :: struct { 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. + 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, @@ -47,6 +47,8 @@ Thread :: struct { */ init_context: Maybe(runtime.Context), + // Indicates whether the thread will free itself when it completes + self_cleanup: bool, creation_allocator: mem.Allocator, } @@ -101,125 +103,46 @@ yield :: proc() { run :: proc(fn: proc(), init_context: Maybe(runtime.Context) = nil, priority := Thread_Priority.Normal) { - thread_proc :: proc(t: ^Thread) { - fn := cast(proc())t.data - fn() - destroy(t) - } - t := create(thread_proc, priority) - t.data = rawptr(fn) - t.init_context = init_context - start(t) + create_and_start(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) { - thread_proc :: proc(t: ^Thread) { - fn := cast(proc(rawptr))t.data - assert(t.user_index >= 1) - data := t.user_args[0] - fn(data) - destroy(t) - } - t := create(thread_proc, priority) - t.data = rawptr(fn) - t.user_index = 1 - t.user_args = data - t.init_context = init_context - start(t) + create_and_start_with_data(data, fn, init_context, priority, true) } run_with_poly_data :: proc(data: $T, fn: proc(data: T), init_context: Maybe(runtime.Context) = nil, priority := Thread_Priority.Normal) where size_of(T) <= size_of(rawptr) { - thread_proc :: proc(t: ^Thread) { - fn := cast(proc(T))t.data - assert(t.user_index >= 1) - data := (^T)(&t.user_args[0])^ - fn(data) - destroy(t) - } - t := create(thread_proc, priority) - t.data = rawptr(fn) - t.user_index = 1 - data := data - mem.copy(&t.user_args[0], &data, size_of(data)) - t.init_context = init_context - start(t) + create_and_start_with_poly_data(data, fn, init_context, priority, true) } run_with_poly_data2 :: proc(arg1: $T1, arg2: $T2, fn: proc(T1, T2), init_context: Maybe(runtime.Context) = nil, priority := Thread_Priority.Normal) where size_of(T1) <= size_of(rawptr), size_of(T2) <= size_of(rawptr) { - thread_proc :: proc(t: ^Thread) { - fn := cast(proc(T1, T2))t.data - assert(t.user_index >= 2) - arg1 := (^T1)(&t.user_args[0])^ - arg2 := (^T2)(&t.user_args[1])^ - fn(arg1, arg2) - destroy(t) - } - t := create(thread_proc, priority) - t.data = rawptr(fn) - t.user_index = 2 - arg1, arg2 := arg1, arg2 - mem.copy(&t.user_args[0], &arg1, size_of(arg1)) - mem.copy(&t.user_args[1], &arg2, size_of(arg2)) - t.init_context = init_context - start(t) + create_and_start_with_poly_data2(arg1, arg2, fn, init_context, priority, true) } 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) where size_of(T1) <= size_of(rawptr), size_of(T2) <= size_of(rawptr), size_of(T3) <= size_of(rawptr) { - thread_proc :: proc(t: ^Thread) { - fn := cast(proc(T1, T2, T3))t.data - assert(t.user_index >= 3) - arg1 := (^T1)(&t.user_args[0])^ - arg2 := (^T2)(&t.user_args[1])^ - arg3 := (^T3)(&t.user_args[2])^ - fn(arg1, arg2, arg3) - destroy(t) - } - t := create(thread_proc, priority) - t.data = rawptr(fn) - t.user_index = 3 - arg1, arg2, arg3 := arg1, arg2, arg3 - mem.copy(&t.user_args[0], &arg1, size_of(arg1)) - mem.copy(&t.user_args[1], &arg2, size_of(arg2)) - mem.copy(&t.user_args[2], &arg3, size_of(arg3)) - t.init_context = init_context - start(t) + create_and_start_with_poly_data3(arg1, arg2, arg3, fn, init_context, priority, true) } 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) where size_of(T1) <= size_of(rawptr), size_of(T2) <= size_of(rawptr), size_of(T3) <= size_of(rawptr) { + create_and_start_with_poly_data4(arg1, arg2, arg3, arg4, fn, init_context, priority, true) +} + + +create_and_start :: proc(fn: proc(), init_context: Maybe(runtime.Context) = nil, priority := Thread_Priority.Normal, self_cleanup := false) -> ^Thread { thread_proc :: proc(t: ^Thread) { - fn := cast(proc(T1, T2, T3, T4))t.data - assert(t.user_index >= 4) - arg1 := (^T1)(&t.user_args[0])^ - arg2 := (^T2)(&t.user_args[1])^ - arg3 := (^T3)(&t.user_args[2])^ - arg4 := (^T4)(&t.user_args[3])^ - fn(arg1, arg2, arg3, arg4) - destroy(t) + fn := cast(proc())t.data + fn() } t := create(thread_proc, priority) t.data = rawptr(fn) - t.user_index = 4 - arg1, arg2, arg3, arg4 := arg1, arg2, arg3, arg4 - mem.copy(&t.user_args[0], &arg1, size_of(arg1)) - mem.copy(&t.user_args[1], &arg2, size_of(arg2)) - mem.copy(&t.user_args[2], &arg3, size_of(arg3)) - mem.copy(&t.user_args[3], &arg4, size_of(arg4)) - t.init_context = init_context - start(t) -} - - - -create_and_start :: proc(fn: Thread_Proc, init_context: Maybe(runtime.Context) = nil, priority := Thread_Priority.Normal) -> ^Thread { - t := create(fn, priority) + t.self_cleanup = self_cleanup t.init_context = init_context start(t) return t @@ -228,7 +151,7 @@ create_and_start :: proc(fn: Thread_Proc, init_context: Maybe(runtime.Context) = -create_and_start_with_data :: proc(data: rawptr, fn: proc(data: rawptr), init_context: Maybe(runtime.Context) = nil, priority := Thread_Priority.Normal) -> ^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) -> ^Thread { thread_proc :: proc(t: ^Thread) { fn := cast(proc(rawptr))t.data assert(t.user_index >= 1) @@ -239,12 +162,13 @@ create_and_start_with_data :: proc(data: rawptr, fn: proc(data: rawptr), init_co t.data = rawptr(fn) t.user_index = 1 t.user_args = data + t.self_cleanup = self_cleanup t.init_context = init_context start(t) return t } -create_and_start_with_poly_data :: proc(data: $T, fn: proc(data: T), init_context: Maybe(runtime.Context) = nil, priority := Thread_Priority.Normal) -> ^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) -> ^Thread where size_of(T) <= size_of(rawptr) { thread_proc :: proc(t: ^Thread) { fn := cast(proc(T))t.data @@ -257,12 +181,13 @@ create_and_start_with_poly_data :: proc(data: $T, fn: proc(data: T), init_contex t.user_index = 1 data := data mem.copy(&t.user_args[0], &data, size_of(data)) + t.self_cleanup = self_cleanup t.init_context = init_context start(t) return t } -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) -> ^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) -> ^Thread where size_of(T1) <= size_of(rawptr), size_of(T2) <= size_of(rawptr) { thread_proc :: proc(t: ^Thread) { @@ -278,12 +203,13 @@ create_and_start_with_poly_data2 :: proc(arg1: $T1, arg2: $T2, fn: proc(T1, T2), arg1, arg2 := arg1, arg2 mem.copy(&t.user_args[0], &arg1, size_of(arg1)) mem.copy(&t.user_args[1], &arg2, size_of(arg2)) + t.self_cleanup = self_cleanup t.init_context = init_context start(t) return t } -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) -> ^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) -> ^Thread where size_of(T1) <= size_of(rawptr), size_of(T2) <= size_of(rawptr), size_of(T3) <= size_of(rawptr) { @@ -302,11 +228,12 @@ create_and_start_with_poly_data3 :: proc(arg1: $T1, arg2: $T2, arg3: $T3, fn: pr mem.copy(&t.user_args[0], &arg1, size_of(arg1)) mem.copy(&t.user_args[1], &arg2, size_of(arg2)) mem.copy(&t.user_args[2], &arg3, size_of(arg3)) + t.self_cleanup = self_cleanup t.init_context = init_context start(t) return t } -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) -> ^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) -> ^Thread where size_of(T1) <= size_of(rawptr), size_of(T2) <= size_of(rawptr), size_of(T3) <= size_of(rawptr) { @@ -327,6 +254,7 @@ create_and_start_with_poly_data4 :: proc(arg1: $T1, arg2: $T2, arg3: $T3, arg4: mem.copy(&t.user_args[1], &arg2, size_of(arg2)) mem.copy(&t.user_args[2], &arg3, size_of(arg3)) mem.copy(&t.user_args[3], &arg4, size_of(arg4)) + t.self_cleanup = self_cleanup t.init_context = init_context start(t) return t @@ -360,4 +288,4 @@ _maybe_destroy_default_temp_allocator :: proc(init_context: Maybe(runtime.Contex if context.temp_allocator.procedure == runtime.default_temp_allocator_proc { runtime.default_temp_allocator_destroy(auto_cast context.temp_allocator.data) } -}
\ No newline at end of file +} |