From 4d11f83f706416c255374517efdcb82d37e42819 Mon Sep 17 00:00:00 2001 From: Bruce Hill Date: Tue, 26 Nov 2024 13:57:00 -0500 Subject: [PATCH] Add some examples to the repo --- examples/threads/threads.tm | 106 ++++++++++++++++++++++++++ examples/tomo-install/tomo-install.tm | 74 ++++++++++++++++++ 2 files changed, 180 insertions(+) create mode 100644 examples/threads/threads.tm create mode 100644 examples/tomo-install/tomo-install.tm diff --git a/examples/threads/threads.tm b/examples/threads/threads.tm new file mode 100644 index 0000000..8be568c --- /dev/null +++ b/examples/threads/threads.tm @@ -0,0 +1,106 @@ +use + +struct Mutex(_mutex:@Memory): + func new(->Mutex): + return Mutex( + inline C : @Memory { + 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 do_locked(m:Mutex, fn:func(); inline): + inline C { + pthread_mutex_lock((pthread_mutex_t*)$m.$_mutex); + } + fn() + inline C { + pthread_mutex_unlock((pthread_mutex_t*)$m.$_mutex); + } + +struct ThreadCondition(_cond:@Memory): + func new(->ThreadCondition): + return ThreadCondition( + inline C : @Memory { + 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(c:ThreadCondition, m:Mutex; inline): + inline C { + pthread_cond_wait((pthread_cond_t*)$c.$_cond, (pthread_mutex_t*)$m.$_mutex); + } + + func signal(c:ThreadCondition; inline): + inline C { + pthread_cond_signal((pthread_cond_t*)$c.$_cond); + } + + func broadcast(c:ThreadCondition; inline): + inline C { + pthread_cond_broadcast((pthread_cond_t*)$c.$_cond); + } + +struct Guard(mutex=Mutex.new(), cond=ThreadCondition.new()): + func guarded(g:Guard, fn:func(); inline): + g.mutex:do_locked(fn) + g.cond:signal() + + func wait(g:Guard): + g.cond:wait(g.mutex) + +struct PThread(_thread:@Memory): + func new(fn:func() -> PThread): + return PThread( + inline C : @Memory { + pthread_t *thread = new(pthread_t); + pthread_create(thread, NULL, $fn.fn, $fn.userdata); + thread + } + ) + + func join(t:PThread): + inline C { + pthread_join(*(pthread_t*)$t.$_thread, NULL); + } + + func cancel(t:PThread): + inline C { + pthread_cancel(*(pthread_t*)$t.$_thread); + } + + func detatch(t:PThread): + inline C { + pthread_detach(*(pthread_t*)$t.$_thread); + } + +func main(): + g := Guard() + queue := @[10, 20] + + t := PThread.new(func(): + say("In another thread!") + item := @NONE:Int + while item[] != 30: + g:guarded(func(): + while queue.length == 0: + g:wait() + + item[] = queue[1] + queue:remove_at(1) + ) + say("Processing: $item") + sleep(0.01) + say("All done!") + ) + >> t + >> sleep(1) + >> g:guarded(func(): + queue:insert(30) + ) + >> t:join() diff --git a/examples/tomo-install/tomo-install.tm b/examples/tomo-install/tomo-install.tm new file mode 100644 index 0000000..998462d --- /dev/null +++ b/examples/tomo-install/tomo-install.tm @@ -0,0 +1,74 @@ + +_USAGE := " + tomo-install file.tm... +" + +_HELP := " + tomo-install: a tool for installing libraries for the Tomo language + Usage: $_USAGE +" + +func find_urls(path:Path -> [Text]): + urls := @[:Text] + if path:is_directory(): + for f in path:children(): + urls:insert_all(find_urls(f)) + else if path:is_file() and path:ends_with(".tm"): + for line in path:by_line()!: + if m := line:matches($/use{space}{url}/) or line:matches($/{id}{space}:={space}use{space}{url}/): + urls:insert(m[-1]) + return urls + +func main(paths:[Path]): + if paths.length == 0: + paths = [(./)] + + urls := (++: find_urls(p) for p in paths) or [:Text] + + github_token := (~/.config/tomo/github-token):read() + + (~/.local/share/tomo/installed):create_directory() + (~/.local/share/tomo/lib):create_directory() + + for url in urls: + original_url := url + url_without_protocol := url:trim($|http{0-1 s}://|, trim_right=no) + hash := $(echo -n @url_without_protocol | sha256sum):run()!:slice(to=32) + if (~/.local/share/tomo/installed/$hash):is_directory(): + say("Already installed: $url") + skip + + alias := NONE:Text + curl_flags := ["-L"] + if github := url_without_protocol:matches($|github.com/{!/}/{!/}#{..}|): + user := github[1] + repo := github[2] + tag := github[3] + url = "https://api.github.com/repos/$user/$repo/tarball/$tag" + alias = "$(repo:trim($/tomo-/, trim_right=no)).$(tag).$(user)" + if github_token: + curl_flags ++= ["-H", "Authorization: Bearer $github_token"] + curl_flags ++= [ + "-H", "Accept: application/vnd.github+json", + "-H", "X-GitHub-Api-Version: 2022-11-28", + ] + + (~/.local/share/tomo/downloads/$hash):create_directory() + say($Shell@` + set -euo pipefail + cd ~/.local/share/tomo/downloads/@hash + curl @curl_flags @url | tar xz -C ~/.local/share/tomo/installed --strip-components=1 --one-top-level=@hash + echo @original_url > ~/.local/share/tomo/installed/@hash/source.url + tomo -L ~/.local/share/tomo/installed/@hash + ln -f -s ../installed/@hash/lib@hash.so ~/.local/share/tomo/lib/lib@hash.so + `:run()!) + + if alias: + say($( + set -exuo pipefail + ln -f -s @hash ~/.local/share/tomo/installed/@alias + ln -f -s lib@hash.so ~/.local/share/tomo/lib/lib@alias.so + ):run()!) + + say("$\[1]Installed $url!$\[]") +