From 76016800556fb110dc9a857b98f925cd24574061 Mon Sep 17 00:00:00 2001 From: Daniel Kolesa Date: Thu, 21 Apr 2022 05:08:19 +0200 Subject: [PATCH] add threads dependency into meson and update readme --- README.md | 35 +++++++++++++++++------------------ doc/main_page.md | 1 + meson.build | 2 ++ src/meson.build | 3 +++ 4 files changed, 23 insertions(+), 18 deletions(-) diff --git a/README.md b/README.md index 69dcf71..dc7d091 100644 --- a/README.md +++ b/README.md @@ -45,6 +45,7 @@ There's a variety of things that set this implementation apart: uses is allocated through it; that gives you complete control over its memory (for tracking, sandboxing, limits, etc.) * A large degree of memory safety, with no manual management +* Thread-safe by default * Strings are interned, with a single reference counted instance of any string existing at a time, which lowers memory usage and simplifies its management @@ -65,7 +66,6 @@ More features and enhancements are planned, such as: * Improved support for debugging information (line information tracking at runtime rather than just compile-time) -* Thread safety Right now, the codebase is unstable, but quickly approaching production readiness. You are encouraged to test things and report bugs; contributions @@ -81,25 +81,24 @@ thread, which owns all variables and most state. Based on the main thread you can create side threads, which share a lot of state with the main thread but have their own call stack. -In the future, accesses to "global" state (the state shared between threads) -will be made thread safe. +These threads are not thread-safe by themselves, but as long as you ensure +that concurrent access to them is protected, libcubescript is thread-safe, +i.e. any internal shared state between libcubescript threads is synchronized. +That means you can simply create several libcubescript threads, use them from +different OS threads, and you won't run into any trouble. -That means you will be able to use the library in multithreaded contexts, as -long as you make sure to only use any Cubescript thread from at most one -real thread at a time (accesses to thread state will not be thread-safe). +Additionally, this means libcubescript threads are coroutine-safe; if you +call into one from a coroutine and yield somewhere mid-command, you can still +access and run code on other libcubescript threads completely safely. Once +you resume the coroutine, it will continue where it left off (though global +variables may have changed). -Right now, this at least means the library is coroutine-safe. You can call -into a Cubescript thread inside a coroutine, yield somewhere mid-command, -and still be able to access the state safely through other Cubescript -threads. Once you resume the coroutine, it will continue where it left -off, without anything being wrong. - -Since strings are interned and reference counted, this is also geared -towards thread safety - any API returning a string will give you your own -reference, which means nothing can free it while you are still using it. -Similarly, things taking string references will generally increment the -count for their own purposes. This all happens automatically thanks to -C++'s scoped value handling. +Since strings are interned and reference counted, string references returned +by libcubescript are also safe, as you get your own reference and nothing +can touch it. Things taking strings will have their own references, and +the code will ensure that strings live for as long as a reference exists +somewhere. Thanks to C++'s scoped value handling, this is mostly seamless +for the user. ## Building and usage diff --git a/doc/main_page.md b/doc/main_page.md index ec2535e..28dcbce 100644 --- a/doc/main_page.md +++ b/doc/main_page.md @@ -43,6 +43,7 @@ There's a variety of things that set this implementation apart: uses is allocated through it; that gives you complete control over its memory (for tracking, sandboxing, limits, etc.) * A large degree of memory safety, with no manual management +* Thread-safe by default * Strings are interned, with a single reference counted instance of any string existing at a time, which lowers memory usage and simplifies its management diff --git a/meson.build b/meson.build index 79cd51d..2a0e91d 100644 --- a/meson.build +++ b/meson.build @@ -49,6 +49,8 @@ endif build_root = meson.current_build_dir() +thr_dep = dependency('threads') + subdir('include') subdir('src') subdir('tools') diff --git a/src/meson.build b/src/meson.build index 64fef14..0b15942 100644 --- a/src/meson.build +++ b/src/meson.build @@ -36,11 +36,13 @@ if os_uses_dlls and get_option('default_library') == 'both' # do that other than making two different targets... libcubescript_static = static_library('cubescript', libcubescript_src, include_directories: lib_incdirs, + dependencies: thr_dep, cpp_args: lib_cxxflags, install: true ) libcubescript_dynamic = shared_library('cubescript', libcubescript_src, include_directories: lib_incdirs, + dependencies: thr_dep, cpp_args: dyn_cxxflags, install: true, version: meson.project_version() @@ -49,6 +51,7 @@ if os_uses_dlls and get_option('default_library') == 'both' else libcubescript_target = library('cubescript', libcubescript_src, include_directories: lib_incdirs, + dependencies: thr_dep, cpp_args: dyn_cxxflags, install: true, version: meson.project_version()