use types::c; export type pthread_t = [8]u8; type pthread_attr_t = opaque; type pthread_fn = fn(nullable *opaque) nullable *opaque; export type thread_fn = fn(nullable *opaque) void; @symbol("pthread_create") fn pthread_create(thread: nullable *pthread_t, attr: nullable *pthread_attr_t, start_routine: *pthread_fn, arg: nullable *opaque) int; @symbol("pthread_join") fn pthread_join(thread: pthread_t, nullable *nullable *opaque) int; @symbol("pthread_detach") fn pthread_detach(thread: pthread_t) int; type data_wrapper = struct { f: *thread_fn, data: nullable *opaque, }; fn thread_spawn_wrapper(arg: nullable *opaque) nullable *opaque = { let data = arg: *data_wrapper; data.f(data.data); free(data); return null; }; export type error = !void; export type join_handle = struct { thread: pthread_t, }; // spawn a thread // // returns a handle or an error export fn spawn(f: *thread_fn, data: nullable *opaque) (join_handle | error) = { let data: *data_wrapper = alloc(data_wrapper { f = f, data = data, }); let tid: pthread_t = [0...]; let ret = pthread_create(&tid, null, &thread_spawn_wrapper, data); if (ret != 0) { return error; }; return join_handle { thread = tid }; }; // join a thread // // no return value or an error on join export fn join(handle: join_handle) (void | error) = { let ret = pthread_join(handle.thread, null); if (ret != 0) { return error; }; }; // detach a thread. export fn detach(handle: join_handle) (void | error) = { let ret = pthread_detach(handle.thread); if (ret != 0) { return error; }; };