#import "Thread";
global_counter: int;
global_mutex: Mutex;
main :: () {
print("=== Basic Threading ===\n");
basic_threading();
print("\n=== Mutex Example ===\n");
mutex_example();
print("\n=== Thread Pool ===\n");
thread_pool_example();
print("\n=== Work Queue ===\n");
work_queue_example();
print("\n=== Async/Await Pattern ===\n");
async_await_example();
print("\n=== Atomic Operations ===\n");
atomic_example();
}
thread_func :: (data: *void) -> *void #c_call {
id := cast(int) data;
print("Thread % starting\n", id);
for 0..4 {
print("Thread %: iteration %\n", id, it);
sleep_milliseconds(100);
}
print("Thread % finished\n", id);
return null;
}
basic_threading :: () {
thread: Thread;
thread_init(*thread, thread_func, cast(*void) 1);
thread_start(*thread);
for 0..4 {
print("Main: iteration %\n", it);
sleep_milliseconds(100);
}
thread_join(*thread);
thread_deinit(*thread);
print("All threads completed\n");
}
mutex_example :: () {
global_counter = 0;
mutex_init(*global_mutex);
threads: [4]Thread;
for 0..3 {
thread_init(*threads[it], increment_worker, cast(*void) it);
thread_start(*threads[it]);
}
for 0..3 {
thread_join(*threads[it]);
thread_deinit(*threads[it]);
}
mutex_destroy(*global_mutex);
print("Final counter value: % (expected 4000)\n", global_counter);
}
increment_worker :: (data: *void) -> *void #c_call {
id := cast(int) data;
for 0..999 {
mutex_lock(*global_mutex);
global_counter += 1;
mutex_unlock(*global_mutex);
}
print("Worker % completed\n", id);
return null;
}
WorkItem :: struct {
id: int;
data: int;
}
ThreadPool :: struct {
threads: [..]*Thread;
work_queue: [..]WorkItem;
queue_mutex: Mutex;
work_available: Condition_Variable;
shutdown: bool;
}
thread_pool_example :: () {
pool: ThreadPool;
mutex_init(*pool.queue_mutex);
condition_variable_init(*pool.work_available);
defer {
mutex_destroy(*pool.queue_mutex);
condition_variable_destroy(*pool.work_available);
}
for 0..3 {
t := New(Thread);
thread_init(t, pool_worker, *pool);
array_add(*pool.threads, t);
thread_start(t);
}
for 0..9 {
mutex_lock(*pool.queue_mutex);
array_add(*pool.work_queue, .{it, it * it});
condition_variable_signal(*pool.work_available);
mutex_unlock(*pool.queue_mutex);
}
sleep_milliseconds(500);
pool.shutdown = true;
for pool.threads {
condition_variable_broadcast(*pool.work_available);
}
for pool.threads {
thread_join(it);
thread_deinit(it);
free(it);
}
print("Thread pool completed\n");
}
pool_worker :: (data: *void) -> *void #c_call {
pool := cast(*ThreadPool) data;
while true {
mutex_lock(*pool.queue_mutex);
while pool.work_queue.count == 0 && !pool.shutdown {
condition_variable_wait(*pool.work_available, *pool.queue_mutex);
}
if pool.shutdown && pool.work_queue.count == 0 {
mutex_unlock(*pool.queue_mutex);
break;
}
work := pool.work_queue[0];
array_ordered_remove_by_index(*pool.work_queue, 0);
mutex_unlock(*pool.queue_mutex);
print("Worker processing item %: %\n", work.id, work.data);
sleep_milliseconds(50);
}
return null;
}
Task :: struct {
func: (int) -> ();
arg: int;
}
WorkQueue :: struct {
tasks: [..]Task;
mutex: Mutex;
available: Condition_Variable;
}
work_queue_example :: () {
queue: WorkQueue;
mutex_init(*queue.mutex);
condition_variable_init(*queue.available);
defer {
mutex_destroy(*queue.mutex);
condition_variable_destroy(*queue.available);
}
producer: Thread;
thread_init(*producer, (data: *void) -> *void #c_call {
q := cast(*WorkQueue) data;
for 0..4 {
task: Task;
task.func = (x: int) { print("Task executed with %\n", x); };
task.arg = it;
mutex_lock(*q.mutex);
array_add(*q.tasks, task);
condition_variable_signal(*q.available);
mutex_unlock(*q.mutex);
sleep_milliseconds(100);
}
return null;
}, *queue);
thread_start(*producer);
completed := 0;
while completed < 5 {
mutex_lock(*queue.mutex);
while queue.tasks.count == 0 {
condition_variable_wait(*queue.available, *queue.mutex);
}
task := queue.tasks[0];
array_ordered_remove_by_index(*queue.tasks, 0);
mutex_unlock(*queue.mutex);
task.func(task.arg);
completed += 1;
}
thread_join(*producer);
thread_deinit(*producer);
print("Work queue completed\n");
}
Promise :: struct ($T: Type) {
value: T;
completed: bool;
mutex: Mutex;
available: Condition_Variable;
}
async_compute :: (promise: *Promise(int), input: int) #c_call {
sleep_milliseconds(200);
mutex_lock(*promise.mutex);
promise.value = input * input;
promise.completed = true;
condition_variable_signal(*promise.available);
mutex_unlock(*promise.mutex);
return null;
}
async_await_example :: () {
promise: Promise(int);
mutex_init(*promise.mutex);
condition_variable_init(*promise.available);
defer {
mutex_destroy(*promise.mutex);
condition_variable_destroy(*promise.available);
}
thread: Thread;
thread_init(*thread, (data: *void) -> *void #c_call {
args := cast(*AsyncArgs) data;
async_compute(args.promise, args.input);
return null;
}, *promise);
thread_start(*thread);
print("Doing other work while waiting...\n");
sleep_milliseconds(100);
mutex_lock(*promise.mutex);
while !promise.completed {
condition_variable_wait(*promise.available, *promise.mutex);
}
result := promise.value;
mutex_unlock(*promise.mutex);
print("Async result: %\n", result);
thread_join(*thread);
thread_deinit(*thread);
}
AsyncArgs :: struct {
promise: *Promise(int);
input: int;
}
atomic_counter: s64;
atomic_example :: () {
atomic_counter = 0;
threads: [3]Thread;
for 0..2 {
thread_init(*threads[it], atomic_worker, cast(*void) it);
thread_start(*threads[it]);
}
for 0..2 {
thread_join(*threads[it]);
thread_deinit(*threads[it]);
}
print("Atomic counter: %\n", atomic_counter);
}
atomic_worker :: (data: *void) -> *void #c_call {
id := cast(int) data;
for 0..999 {
atomic_add(*atomic_counter, 1);
}
print("Atomic worker % completed\n", id);
return null;
}
atomic_add :: (val: *s64, delta: s64) -> s64 {
#if CPU == .X64 {
result: s64;
#asm {
mov rcx, val;
mov rdx, delta;
lock xadd [rcx], rdx;
mov result, rdx;
}
return result;
} else {
val.* += delta;
return val.*;
}
}
#import "Basic";