Created
October 13, 2024 12:08
-
-
Save quonic/79cc68afb3fe03425649fa4d2cd1a166 to your computer and use it in GitHub Desktop.
A simple custom Odin hello world thread pool example
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import "core:fmt" | |
import "core:thread" | |
// Array of threads | |
threads: [dynamic]^thread.Thread | |
// Pool of data that each thread can access | |
Pool :: struct { | |
strings: [dynamic]string, | |
} | |
pool: Pool | |
main :: proc() { | |
// Initialize our data for the threads | |
pool.strings = {"Hello", "World", "From", "Odin", "Threads"} | |
// Create and run our threads | |
for _, i in pool.strings { | |
// Create the thread | |
t, ok := create_thread(proc(t: ^thread.Thread) { | |
pool := (^Pool)(t.data) | |
fmt.printfln("Thread %d says: %v", t.user_index, pool.strings[t.user_index]) | |
}, i, &pool).? | |
// Run the thread if it was created successfully | |
if ok do run_thread(t) | |
else if !ok do fmt.printfln("Failed to create thread %d", i) | |
} | |
// Wait for all threads to finish | |
for are_threads_running() { | |
// Yield the main thread | |
thread.yield() | |
} | |
} | |
// Thread Management | |
@(init) | |
create_thread_pool :: proc() { | |
// Thanks to VOU-folks for this code: https://github.com/VOU-folks/odin-tcp-server-example/blob/main/main.odin | |
threads = make([dynamic]^thread.Thread, 0) | |
thread_cleaner() | |
} | |
// Destroy the thread pool | |
destroy_thread_pool :: proc() { | |
delete(threads) | |
} | |
// Get the number of running threads | |
get_thread_count :: proc() -> int { | |
return len(threads) | |
} | |
// Check if there are any threads running | |
are_threads_running :: proc() -> bool { | |
return get_thread_count() > 0 | |
} | |
// Create a thread and add it to the pool | |
create_thread :: proc( | |
p: proc(_: ^thread.Thread), | |
id: int, | |
data: ^Pool = nil, | |
) -> Maybe(^thread.Thread) { | |
// Create the thread and check if the thread was created successfully | |
if t := thread.create(p); t == nil { | |
// Return nil if the thread was not created | |
return nil | |
} else { | |
// Set the user index and data | |
t.user_index = id | |
if data != nil { | |
t.data = data | |
} | |
// Add the thread to the pool | |
append(&threads, t) | |
// Return the thread | |
return t | |
} | |
} | |
// Run a thread | |
run_thread :: proc(t: ^thread.Thread) { | |
thread.start(t) | |
} | |
// Clean up threads that are done | |
thread_cleaner :: proc() { | |
// Create a thread that will clean up the other threads | |
t := thread.create( | |
proc(t: ^thread.Thread) { | |
for { | |
// Yield the thread to the OS or other threads | |
thread.yield() | |
// If there are no threads, continue | |
if get_thread_count() == 0 { | |
continue | |
} | |
// Check if any threads are done | |
for i := 0; i < get_thread_count(); { | |
// Check if the thread is done | |
if thr := threads[i]; thread.is_done(thr) { | |
when ODIN_DEBUG { | |
fmt.printf("Thread %d is done\n", thr.user_index) | |
} | |
// Clean up the thread | |
thr.data = nil | |
thread.destroy(thr) | |
ordered_remove(&threads, i) | |
} else { | |
// Move to the next thread | |
i += 1 | |
} | |
} | |
} | |
}, | |
) | |
// Start the thread cleaner | |
thread.start(t) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment