From 45cbcbce3b061f40c99ad03a6f38f92ba3fc63d7 Mon Sep 17 00:00:00 2001 From: Bruce Hill Date: Tue, 18 Mar 2025 17:31:17 -0400 Subject: Pluralize pthreads --- Makefile | 2 +- examples/pthread/pthread.tm | 107 ------------------------------------------ examples/pthreads/pthreads.tm | 107 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 108 insertions(+), 108 deletions(-) delete mode 100644 examples/pthread/pthread.tm create mode 100644 examples/pthreads/pthreads.tm diff --git a/Makefile b/Makefile index 00ef89d7..41a64e16 100644 --- a/Makefile +++ b/Makefile @@ -77,7 +77,7 @@ clean: examples: examples/commands/commands examples/base64/base64 examples/ini/ini examples/game/game \ examples/tomodeps/tomodeps examples/tomo-install/tomo-install examples/wrap/wrap examples/colorful/colorful ./tomo -IL examples/commands examples/shell examples/base64 examples/log examples/ini examples/vectors examples/game \ - examples/http examples/threads examples/tomodeps examples/tomo-install examples/wrap examples/pthread examples/colorful + examples/http examples/threads examples/tomodeps examples/tomo-install examples/wrap examples/pthreads examples/colorful ./tomo examples/learnxiny.tm install: tomo libtomo.so tomo.1 diff --git a/examples/pthread/pthread.tm b/examples/pthread/pthread.tm deleted file mode 100644 index 13d94e40..00000000 --- a/examples/pthread/pthread.tm +++ /dev/null @@ -1,107 +0,0 @@ -# A Posix Threads (pthreads) wrapper -use - -extern pthread_mutex_lock:func(mutex:&pthread_mutex_t -> Int32) -extern pthread_mutex_unlock:func(mutex:&pthread_mutex_t -> Int32) - -struct pthread_mutex_t(; extern, opaque): - func new(->@pthread_mutex_t): - return inline C : @pthread_mutex_t { - pthread_mutex_t *mutex = new(pthread_mutex_t); - pthread_mutex_init(mutex, NULL); - GC_register_finalizer(mutex, (void*)pthread_mutex_destroy, NULL, NULL, NULL); - mutex - } - - func lock(m:&pthread_mutex_t): - fail("Failed to lock mutex") unless pthread_mutex_lock(m) == 0 - - func unlock(m:&pthread_mutex_t): - fail("Failed to unlock mutex") unless pthread_mutex_unlock(m) == 0 - -extern pthread_cond_wait:func(cond:&pthread_cond_t, mutex:&pthread_mutex_t -> Int32) -extern pthread_cond_signal:func(cond:&pthread_cond_t -> Int32) -extern pthread_cond_broadcast:func(cond:&pthread_cond_t -> Int32) - -struct pthread_cond_t(; extern, opaque): - func new(->@pthread_cond_t): - return inline C : @pthread_cond_t { - pthread_cond_t *cond = new(pthread_cond_t); - pthread_cond_init(cond, NULL); - GC_register_finalizer(cond, (void*)pthread_cond_destroy, NULL, NULL, NULL); - cond - } - - func wait(cond:&pthread_cond_t, mutex:&pthread_mutex_t): - fail("Failed to wait on condition") unless pthread_cond_wait(cond, mutex) == 0 - - func signal(cond:&pthread_cond_t): - fail("Failed to signal pthread_cond_t") unless pthread_cond_signal(cond) == 0 - - func broadcast(cond:&pthread_cond_t): - fail("Failed to broadcast pthread_cond_t") unless pthread_cond_broadcast(cond) == 0 - -struct pthread_t(; extern, opaque): - func new(fn:func() -> @pthread_t): - return inline C : @pthread_t { - pthread_t *thread = new(pthread_t); - pthread_create(thread, NULL, _$fn.fn, _$fn.userdata); - thread - } - - func join(p:@pthread_t): inline C { pthread_join(*_$p, NULL); } - func cancel(p:@pthread_t): inline C { pthread_cancel(*_$p); } - func detatch(p:@pthread_t): inline C { pthread_detach(*_$p); } - -struct IntQueue(_queue:@[Int], _mutex:@pthread_mutex_t, _cond:@pthread_cond_t): - func new(initial=[:Int] -> IntQueue): - return IntQueue(@initial, pthread_mutex_t.new(), pthread_cond_t.new()) - - func give(q:IntQueue, n:Int): - begin: q._mutex:lock() - end: q._mutex:unlock() - do: q._queue:insert(n) - q._cond:signal() - - func take(q:IntQueue -> Int): - begin: q._mutex:lock() - end: q._mutex:unlock() - do: - repeat: - if n := q._queue:pop(1): - return n - q._cond:wait(q._mutex) - fail("Unreachable") - -func main(): - jobs := IntQueue.new() - results := IntQueue.new() - - say_mutex := pthread_mutex_t.new() - announce := func(speaker:Text, text:Text): - begin: say_mutex:lock() - end: say_mutex:unlock() - do: say("$\033[2m[$speaker]$\033[m $text") - - worker := pthread_t.new(func(): - say("I'm in the thread!") - repeat: - announce("worker", "waiting for job") - job := jobs:take() - result := job * 10 - announce("worker", "Jobbing $job into $result") - results:give(result) - announce("worker", "Signaled $result") - ) - - for i in 10: - announce("boss", "Pushing job $i") - jobs:give(i) - announce("boss", "Gave job $i") - - for i in 10: - announce("boss", "Getting result...") - result := results:take() - announce("boss", "Got result $result") - - >> worker:cancel() diff --git a/examples/pthreads/pthreads.tm b/examples/pthreads/pthreads.tm new file mode 100644 index 00000000..13d94e40 --- /dev/null +++ b/examples/pthreads/pthreads.tm @@ -0,0 +1,107 @@ +# A Posix Threads (pthreads) wrapper +use + +extern pthread_mutex_lock:func(mutex:&pthread_mutex_t -> Int32) +extern pthread_mutex_unlock:func(mutex:&pthread_mutex_t -> Int32) + +struct pthread_mutex_t(; extern, opaque): + func new(->@pthread_mutex_t): + return inline C : @pthread_mutex_t { + pthread_mutex_t *mutex = new(pthread_mutex_t); + pthread_mutex_init(mutex, NULL); + GC_register_finalizer(mutex, (void*)pthread_mutex_destroy, NULL, NULL, NULL); + mutex + } + + func lock(m:&pthread_mutex_t): + fail("Failed to lock mutex") unless pthread_mutex_lock(m) == 0 + + func unlock(m:&pthread_mutex_t): + fail("Failed to unlock mutex") unless pthread_mutex_unlock(m) == 0 + +extern pthread_cond_wait:func(cond:&pthread_cond_t, mutex:&pthread_mutex_t -> Int32) +extern pthread_cond_signal:func(cond:&pthread_cond_t -> Int32) +extern pthread_cond_broadcast:func(cond:&pthread_cond_t -> Int32) + +struct pthread_cond_t(; extern, opaque): + func new(->@pthread_cond_t): + return inline C : @pthread_cond_t { + pthread_cond_t *cond = new(pthread_cond_t); + pthread_cond_init(cond, NULL); + GC_register_finalizer(cond, (void*)pthread_cond_destroy, NULL, NULL, NULL); + cond + } + + func wait(cond:&pthread_cond_t, mutex:&pthread_mutex_t): + fail("Failed to wait on condition") unless pthread_cond_wait(cond, mutex) == 0 + + func signal(cond:&pthread_cond_t): + fail("Failed to signal pthread_cond_t") unless pthread_cond_signal(cond) == 0 + + func broadcast(cond:&pthread_cond_t): + fail("Failed to broadcast pthread_cond_t") unless pthread_cond_broadcast(cond) == 0 + +struct pthread_t(; extern, opaque): + func new(fn:func() -> @pthread_t): + return inline C : @pthread_t { + pthread_t *thread = new(pthread_t); + pthread_create(thread, NULL, _$fn.fn, _$fn.userdata); + thread + } + + func join(p:@pthread_t): inline C { pthread_join(*_$p, NULL); } + func cancel(p:@pthread_t): inline C { pthread_cancel(*_$p); } + func detatch(p:@pthread_t): inline C { pthread_detach(*_$p); } + +struct IntQueue(_queue:@[Int], _mutex:@pthread_mutex_t, _cond:@pthread_cond_t): + func new(initial=[:Int] -> IntQueue): + return IntQueue(@initial, pthread_mutex_t.new(), pthread_cond_t.new()) + + func give(q:IntQueue, n:Int): + begin: q._mutex:lock() + end: q._mutex:unlock() + do: q._queue:insert(n) + q._cond:signal() + + func take(q:IntQueue -> Int): + begin: q._mutex:lock() + end: q._mutex:unlock() + do: + repeat: + if n := q._queue:pop(1): + return n + q._cond:wait(q._mutex) + fail("Unreachable") + +func main(): + jobs := IntQueue.new() + results := IntQueue.new() + + say_mutex := pthread_mutex_t.new() + announce := func(speaker:Text, text:Text): + begin: say_mutex:lock() + end: say_mutex:unlock() + do: say("$\033[2m[$speaker]$\033[m $text") + + worker := pthread_t.new(func(): + say("I'm in the thread!") + repeat: + announce("worker", "waiting for job") + job := jobs:take() + result := job * 10 + announce("worker", "Jobbing $job into $result") + results:give(result) + announce("worker", "Signaled $result") + ) + + for i in 10: + announce("boss", "Pushing job $i") + jobs:give(i) + announce("boss", "Gave job $i") + + for i in 10: + announce("boss", "Getting result...") + result := results:take() + announce("boss", "Got result $result") + + >> worker:cancel() -- cgit v1.2.3