diff --git a/cheatsheet.md b/cheatsheet.md index 76f87781..1819ddc0 100644 --- a/cheatsheet.md +++ b/cheatsheet.md @@ -153,17 +153,39 @@ This allows you to pass a ChaiScript function to a function requiring `std::vect ## Adding Objects -``` -chai.add(chaiscript::var(somevar), "somevar"); // copied in -chai.add(chaiscript::var(std::ref(somevar)), "somevar"); // by reference, shared between C++ and chai +### `add` — Thread-Local Scoped Variables + +`add` adds an object to the current thread's local scope. The variable is only visible in the +thread that added it. If the variable already exists in the current scope, it is overwritten. + +```cpp +chai.add(chaiscript::var(somevar), "somevar"); // copied in +chai.add(chaiscript::var(std::ref(somevar)), "somevar"); // by reference, shared between C++ and chai auto shareddouble = std::make_shared(4.3); -chai.add(chaiscript::var(shareddouble), "shareddouble"); // by shared_ptr, shared between c++ and chai -chai.add(chaiscript::const_var(somevar), "somevar"); // copied in and made const -chai.add_global_const(chaiscript::const_var(somevar), "somevar"); // global const. Throws if value is non-const, throws if object exists -chai.add_global(chaiscript::var(somevar), "somevar"); // global non-const, throws if object exists -chai.set_global(chaiscript::var(somevar), "somevar"); // global non-const, overwrites existing object +chai.add(chaiscript::var(shareddouble), "shareddouble"); // by shared_ptr, shared between C++ and chai +chai.add(chaiscript::const_var(somevar), "somevar"); // copied in and made const ``` +### `add_global` / `add_global_const` / `set_global` — Global Shared Variables + +Global variables are shared between all threads and are visible from any scope (including inside +functions). Use these when you need a variable accessible everywhere. + +```cpp +chai.add_global_const(chaiscript::const_var(somevar), "somevar"); // global const, throws if value is non-const or object already exists +chai.add_global(chaiscript::var(somevar), "somevar"); // global non-const, throws if object already exists +chai.set_global(chaiscript::var(somevar), "somevar"); // global non-const, overwrites existing or creates new +``` + +### Summary of Differences + +| Method | Scope | Thread Safety | If Name Exists | +|--------|-------|---------------|----------------| +| `add` | Thread-local, current scope | Not shared between threads | Overwrites | +| `add_global` | Global, all scopes and threads | Mutex-protected, shared between threads | Throws exception | +| `add_global_const` | Global, all scopes and threads | Mutex-protected, shared between threads | Throws exception | +| `set_global` | Global, all scopes and threads | Mutex-protected, shared between threads | Overwrites | + ## Adding Namespaces Namespaces will not be populated until `import` is called. diff --git a/unittests/add_vs_add_global.chai b/unittests/add_vs_add_global.chai new file mode 100644 index 00000000..545d880a --- /dev/null +++ b/unittests/add_vs_add_global.chai @@ -0,0 +1,43 @@ +// Test demonstrating the difference between add (local scope) and add_global/set_global (global scope) +// See issue #554 + +// --- Local variables (var / add) are scoped --- +// A local variable defined in a block is not visible outside that block +var local_val = 10 +assert_equal(local_val, 10) + +// Local variables can be reassigned in scope +local_val = 20 +assert_equal(local_val, 20) + +// Local variables inside a function are not visible outside +def set_local() { + var func_local = 99 + assert_equal(func_local, 99) +} +set_local() + +// --- Globals (add_global) are visible everywhere, including inside functions --- +var g_val = 42 +add_global(g_val, "my_global") + +def check_global() { + assert_equal(my_global, 42) +} +check_global() + +// add_global throws if the global already exists +assert_throws("Name already exists in current context my_global", fun() { add_global(1, "my_global") }) + +// --- set_global overwrites an existing global --- +set_global(100, "my_global") +assert_equal(my_global, 100) + +def check_global_updated() { + assert_equal(my_global, 100) +} +check_global_updated() + +// set_global can also create a new global if it doesn't exist +set_global(77, "new_global") +assert_equal(new_global, 77)