diff options
| -rw-r--r-- | std/thread.zc | 60 | ||||
| -rw-r--r-- | tests/std/test_thread.zc | 42 |
2 files changed, 91 insertions, 11 deletions
diff --git a/std/thread.zc b/std/thread.zc index 78d2547..da21772 100644 --- a/std/thread.zc +++ b/std/thread.zc @@ -25,9 +25,13 @@ raw { z_closure_T *closure = (z_closure_T*)c; void (*f)(void*) = (void(*)(void*))closure->func; f(closure->ctx); - free(c); + free(c); return NULL; } + + static int _z_thread_equal(void* handle1, void* handle2) { + return pthread_equal((pthread_t)handle1, (pthread_t)handle2); + } static int _z_thread_spawn(void *ctx_copy, size_t *out_handle) { pthread_t pt; @@ -41,6 +45,14 @@ raw { static int _z_thread_join(void *handle) { return (int)pthread_join((pthread_t)handle, NULL); } + + static int _z_thread_detach(void* handle) { + return pthread_detach((pthread_t)handle); + } + + static int _z_thread_cancel(void* handle) { + return pthread_cancel((pthread_t)handle); + } static void _z_mutex_init(void *ptr) { pthread_mutex_init((pthread_mutex_t*)ptr, NULL); @@ -63,8 +75,11 @@ raw { } } +extern fn _z_thread_equal(handle1: void*, handle2: void*) -> c_int; extern fn _z_thread_spawn(ctx: void*, out: usize*) -> c_int; extern fn _z_thread_join(handle: void*) -> c_int; +extern fn _z_thread_detach(handle: void*) -> c_int; +extern fn _z_thread_cancel(handle: void*) -> c_int; extern fn _z_mutex_init(ptr: void*); extern fn _z_mutex_lock(ptr: void*); extern fn _z_mutex_unlock(ptr: void*); @@ -74,10 +89,17 @@ extern fn _z_usleep(micros: c_int); struct Thread { - handle: void*; + handle: void*; } impl Thread { + fn eq(self, other: const Thread) -> bool { + return _z_thread_equal(self.handle, other.handle); + } + fn neq(self, other: const Thread) -> bool { + return !(self == other); + } + fn spawn(func: fn()) -> Result<Thread> { let out_handle: usize = 0; @@ -86,11 +108,10 @@ impl Thread { memcpy(ctx, &func, 16); - let ret = _z_thread_spawn(ctx, &out_handle); - let zero: c_int = 0; - if (ret != zero) { - // Failed to spawn - free(ctx); + let ret = _z_thread_spawn(ctx_copy, &t); + + if ret != 0 { + free(ctx_copy); return Result<Thread>::Err("Failed to create thread"); } @@ -98,9 +119,26 @@ impl Thread { } fn join(self) -> Result<bool> { - let ret = _z_thread_join(self.handle); - let zero: c_int = 0; - if (ret != zero) return Result<bool>::Err("Join failed"); + let err = _z_thread_join(self.handle); + if err { + return Result<bool>::Err("Join failed"); + } + return Result<bool>::Ok(true); + } + + fn detach(self) -> Result<bool> { + let err = _z_thread_detach(self.handle); + if err { + return Result<bool>::Err("Detach failed"); + } + return Result<bool>::Ok(true); + } + + fn cancel(self) -> Result<bool> { + let err = _z_thread_cancel(self.handle); + if err { + return Result<bool>::Err("Cancel failed"); + } return Result<bool>::Ok(true); } } @@ -125,7 +163,7 @@ impl Mutex { } fn free(self) { - if (self.handle) { + if self.handle { _z_mutex_destroy(self.handle); free(self.handle); self.handle = NULL; diff --git a/tests/std/test_thread.zc b/tests/std/test_thread.zc new file mode 100644 index 0000000..42fa82e --- /dev/null +++ b/tests/std/test_thread.zc @@ -0,0 +1,42 @@ +import "std/thread.zc" + +test "Thread Spawn and Join" { + "Testing thread spawn and join"; + + let spawn_result = Thread::spawn(fn(){ + "Running on a separate thread"; + }); + assert(spawn_result.is_ok(), "Thread spawn has failed"); + + let thr = spawn_result.unwrap(); + let join_result = thr.join(); + assert(join_result.is_ok(), "Thread join has failed"); +} + +test "Thread Spawn and Detach" { + "Testing thread spawn and detach"; + + let spawn_result = Thread::spawn(fn(){ + "Detached thread, this line might print later."; + }); + assert(spawn_result.is_ok(), "Thread spawn has failed"); + + let thr = spawn_result.unwrap(); + let detach_result = thr.detach(); + assert(detach_result.is_ok(), "Thread detach has failed"); +} + +test "Thread Spawn and Cancel" { + "Testing thread spawn and cancel"; + + let spawn_result = Thread::spawn(fn(){ + "Thread running indefinitely..."; + while true { + } + }); + assert(spawn_result.is_ok(), "Thread spawn has failed"); + + let thr = spawn_result.unwrap(); + let cancel_result = thr.cancel(); + assert(cancel_result.is_ok(), "Thread cancel has failed"); +} |
