summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--std/thread.zc60
-rw-r--r--tests/std/test_thread.zc42
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");
+}