From bd3fe0cac583739bc0d7c4b5c8f301bb350abca0 Mon Sep 17 00:00:00 2001 From: Andy Belle-Isle Date: Fri, 30 Aug 2019 00:19:31 -0400 Subject: Renamed lib to deps so github will ignore it for language stats --- deps/sol2/examples/source/docs/as_function.cpp | 21 ++++ .../docs/as_function_usertype_member_variable.cpp | 28 +++++ deps/sol2/examples/source/docs/as_table_ipairs.cpp | 14 +++ deps/sol2/examples/source/docs/coroutine_main.cpp | 51 ++++++++ .../sol2/examples/source/docs/coroutine_thread.cpp | 37 ++++++ deps/sol2/examples/source/docs/inheritance.cpp | 28 +++++ deps/sol2/examples/source/docs/my_panic.cpp | 26 ++++ .../source/docs/preparing_environments.cpp | 29 +++++ .../examples/source/docs/references_in_lambdas.cpp | 33 +++++ .../examples/source/docs/runtime_extension.cpp | 28 +++++ .../sol2/examples/source/docs/simple_functions.cpp | 18 +++ deps/sol2/examples/source/docs/simple_structs.cpp | 32 +++++ .../examples/source/docs/state_script_safe.cpp | 35 ++++++ deps/sol2/examples/source/docs/state_transfer.cpp | 48 ++++++++ deps/sol2/examples/source/docs/std_thread.cpp | 134 +++++++++++++++++++++ 15 files changed, 562 insertions(+) create mode 100644 deps/sol2/examples/source/docs/as_function.cpp create mode 100644 deps/sol2/examples/source/docs/as_function_usertype_member_variable.cpp create mode 100644 deps/sol2/examples/source/docs/as_table_ipairs.cpp create mode 100644 deps/sol2/examples/source/docs/coroutine_main.cpp create mode 100644 deps/sol2/examples/source/docs/coroutine_thread.cpp create mode 100644 deps/sol2/examples/source/docs/inheritance.cpp create mode 100644 deps/sol2/examples/source/docs/my_panic.cpp create mode 100644 deps/sol2/examples/source/docs/preparing_environments.cpp create mode 100644 deps/sol2/examples/source/docs/references_in_lambdas.cpp create mode 100644 deps/sol2/examples/source/docs/runtime_extension.cpp create mode 100644 deps/sol2/examples/source/docs/simple_functions.cpp create mode 100644 deps/sol2/examples/source/docs/simple_structs.cpp create mode 100644 deps/sol2/examples/source/docs/state_script_safe.cpp create mode 100644 deps/sol2/examples/source/docs/state_transfer.cpp create mode 100644 deps/sol2/examples/source/docs/std_thread.cpp (limited to 'deps/sol2/examples/source/docs') diff --git a/deps/sol2/examples/source/docs/as_function.cpp b/deps/sol2/examples/source/docs/as_function.cpp new file mode 100644 index 0000000..ef9ac61 --- /dev/null +++ b/deps/sol2/examples/source/docs/as_function.cpp @@ -0,0 +1,21 @@ +#define SOL_ALL_SAFETIES_ON 1 +#include + +int main () { + struct callable { + int operator()( int a, bool b ) { + return a + (b ? 10 : 20); + } + }; + + + sol::state lua; + // Binds struct as userdata + // can still be callable, but beware + // caveats + lua.set( "not_func", callable() ); + // Binds struct as function + lua.set( "func", sol::as_function( callable() ) ); + // equivalent: lua.set_function( "func", callable() ); + // equivalent: lua["func"] = callable(); +} diff --git a/deps/sol2/examples/source/docs/as_function_usertype_member_variable.cpp b/deps/sol2/examples/source/docs/as_function_usertype_member_variable.cpp new file mode 100644 index 0000000..3907b13 --- /dev/null +++ b/deps/sol2/examples/source/docs/as_function_usertype_member_variable.cpp @@ -0,0 +1,28 @@ +#define SOL_ALL_SAFETIES_ON 1 +#include + +int main () { + class B { + public: + int bvar = 24; + }; + + sol::state lua; + lua.open_libraries(sol::lib::base); + lua.new_usertype("B", + // bind as variable + "b", &B::bvar, + // bind as function + "f", sol::as_function(&B::bvar) + ); + + B b; + lua.set("b", &b); + lua.script(R"(x = b:f() + y = b.b + assert(x == 24) + assert(y == 24) + )"); + + return 0; +} diff --git a/deps/sol2/examples/source/docs/as_table_ipairs.cpp b/deps/sol2/examples/source/docs/as_table_ipairs.cpp new file mode 100644 index 0000000..43978ce --- /dev/null +++ b/deps/sol2/examples/source/docs/as_table_ipairs.cpp @@ -0,0 +1,14 @@ +#define SOL_ALL_SAFETIES_ON 1 +#include + +#include + +int main (int, char*[]) { + + sol::state lua; + lua.open_libraries(); + lua.set("my_table", sol::as_table(std::vector{ 1, 2, 3, 4, 5 })); + lua.script("for k, v in ipairs(my_table) do print(k, v) assert(k == v) end"); + + return 0; +} diff --git a/deps/sol2/examples/source/docs/coroutine_main.cpp b/deps/sol2/examples/source/docs/coroutine_main.cpp new file mode 100644 index 0000000..8913887 --- /dev/null +++ b/deps/sol2/examples/source/docs/coroutine_main.cpp @@ -0,0 +1,51 @@ +#define SOL_ALL_SAFTIES_ON 1 +#include + +#include + +int main() { + const auto& co_lua_script = R"( +function loop() + while counter ~= 30 + do + coroutine.yield(counter); + counter = counter + 1; + end + return counter +end +)"; + + sol::state lua; + lua.open_libraries(sol::lib::base, sol::lib::coroutine); + /* + lua.script_file("co.lua"); + we load string directly rather than use a file + */ + lua.script(co_lua_script); + sol::coroutine loop_coroutine = lua["loop"]; + // set counter variable in C++ + // (can set it to something else to + // have loop_coroutine() yield different values) + lua["counter"] = 20; + + // example of using and re-using coroutine + // you do not have to use coroutines in a loop, + // this is just the example + + // we start from 0; + // we want 10 values, and we only want to + // run if the coroutine "loop_coroutine" is valid + for (int counter = 0; counter < 10 && loop_coroutine; ++counter) { + // Alternative: counter < 10 && cr.valid() + + // Call the coroutine, does the computation and then suspends + // once it returns, we get the value back from the return + // and then can use it + // we can either leave the coroutine like that can come to it later, + // or loop back around + int value = loop_coroutine(); + std::cout << "In C++: " << value << std::endl; + } + + return 0; +} diff --git a/deps/sol2/examples/source/docs/coroutine_thread.cpp b/deps/sol2/examples/source/docs/coroutine_thread.cpp new file mode 100644 index 0000000..5824f9a --- /dev/null +++ b/deps/sol2/examples/source/docs/coroutine_thread.cpp @@ -0,0 +1,37 @@ +#define SOL_ALL_SAFTIES_ON 1 +#include + +#include + +int main() { + const auto& co_lua_script = R"( +function loop() + while counter ~= 30 + do + coroutine.yield(counter); + counter = counter + 1; + end + return counter +end +)"; + + sol::state lua; + lua.open_libraries(sol::lib::base, sol::lib::coroutine); + /* + lua.script_file("co.lua"); + we load string directly rather than use a file + */ + lua.script(co_lua_script); + sol::thread runner = sol::thread::create(lua.lua_state()); + sol::state_view runnerstate = runner.state(); + sol::coroutine loop_coroutine = lua["loop"]; + lua["counter"] = 20; + + for (int counter = 0; counter < 10 && loop_coroutine; ++counter) { + // Call the coroutine, does the computation and then suspends + int value = loop_coroutine(); + std::cout << "value is " << value << std::endl; + } + + return 0; +} diff --git a/deps/sol2/examples/source/docs/inheritance.cpp b/deps/sol2/examples/source/docs/inheritance.cpp new file mode 100644 index 0000000..b1c87f0 --- /dev/null +++ b/deps/sol2/examples/source/docs/inheritance.cpp @@ -0,0 +1,28 @@ +#define SOL_ALL_SAFETIES_ON 1 +#include + +struct A { + int a = 10; + virtual int call() { return 0; } + virtual ~A(){} +}; +struct B : A { + int b = 11; + virtual int call() override { return 20; } +}; + +int main (int, char*[]) { + + sol::state lua; + + lua.new_usertype( "A", + "call", &A::call + ); + + lua.new_usertype( "B", + "call", &B::call, + sol::base_classes, sol::bases() + ); + + return 0; +} diff --git a/deps/sol2/examples/source/docs/my_panic.cpp b/deps/sol2/examples/source/docs/my_panic.cpp new file mode 100644 index 0000000..aee5714 --- /dev/null +++ b/deps/sol2/examples/source/docs/my_panic.cpp @@ -0,0 +1,26 @@ +#define SOL_ALL_SAFETIES_ON 1 +#include +#include + +inline void my_panic(sol::optional maybe_msg) { + std::cerr << "Lua is in a panic state and will now abort() the application" << std::endl; + if (maybe_msg) { + const std::string& msg = maybe_msg.value(); + std::cerr << "\terror message: " << msg << std::endl; + } + // When this function exits, Lua will exhibit default behavior and abort() +} + +int main (int, char*[]) { + sol::state lua(sol::c_call); + // or, if you already have a lua_State* L + // lua_atpanic( L, sol::c_call ); + // or, with state/state_view: + // sol::state_view lua(L); + // lua.set_panic( sol::c_call ); + + // uncomment the below to see + //lua.script("boom_goes.the_dynamite"); + + return 0; +} diff --git a/deps/sol2/examples/source/docs/preparing_environments.cpp b/deps/sol2/examples/source/docs/preparing_environments.cpp new file mode 100644 index 0000000..f3820f7 --- /dev/null +++ b/deps/sol2/examples/source/docs/preparing_environments.cpp @@ -0,0 +1,29 @@ +#define SOL_ALL_SAFETIES_ON 1 +#include + +int main (int, char*[]) { + sol::state lua; + lua.open_libraries(); + sol::environment my_env(lua, sol::create); + // set value, and we need to explicitly allow for + // access to "print", since a new environment hides + // everything that's not defined inside of it + // NOTE: hiding also hides library functions (!!) + // BE WARNED + my_env["var"] = 50; + my_env["print"] = lua["print"]; + + sol::environment my_other_env(lua, sol::create, lua.globals()); + // do not need to explicitly allow access to "print", + // since we used the "Set a fallback" version + // of the sol::environment constructor + my_other_env["var"] = 443; + + // output: 50 + lua.script("print(var)", my_env); + + // output: 443 + lua.script("print(var)", my_other_env); + + return 0; +} \ No newline at end of file diff --git a/deps/sol2/examples/source/docs/references_in_lambdas.cpp b/deps/sol2/examples/source/docs/references_in_lambdas.cpp new file mode 100644 index 0000000..f681d2a --- /dev/null +++ b/deps/sol2/examples/source/docs/references_in_lambdas.cpp @@ -0,0 +1,33 @@ +#define SOL_ALL_SAFETIES_ON 1 +#include + +#include + +int main(int, char*[]) { + + struct test { + int blah = 0; + }; + + test t; + sol::state lua; + lua.set_function("f", [&t]() { + return t; + }); + lua.set_function("g", [&t]() -> test& { + return t; + }); + + lua.script("t1 = f()"); + lua.script("t2 = g()"); + + test& from_lua_t1 = lua["t1"]; + test& from_lua_t2 = lua["t2"]; + + // not the same: 'f' lambda copied + c_assert(&from_lua_t1 != &t); + // the same: 'g' lambda returned reference + c_assert(&from_lua_t2 == &t); + + return 0; +} diff --git a/deps/sol2/examples/source/docs/runtime_extension.cpp b/deps/sol2/examples/source/docs/runtime_extension.cpp new file mode 100644 index 0000000..9d36d0d --- /dev/null +++ b/deps/sol2/examples/source/docs/runtime_extension.cpp @@ -0,0 +1,28 @@ +#define SOL_ALL_SAFETIES_ON 1 +#include + +#include + +struct object { + int value = 0; +}; + +int main (int, char*[]) { + + std::cout << "==== runtime_extension =====" << std::endl; + + sol::state lua; + lua.open_libraries(sol::lib::base); + + lua.new_usertype( "object" ); + + // runtime additions: through the sol API + lua["object"]["func"] = [](object& o) { return o.value; }; + // runtime additions: through a lua script + lua.script("function object:print () print(self:func()) end"); + + // see it work + lua.script("local obj = object.new() \n obj:print()"); + + return 0; +} diff --git a/deps/sol2/examples/source/docs/simple_functions.cpp b/deps/sol2/examples/source/docs/simple_functions.cpp new file mode 100644 index 0000000..c49c853 --- /dev/null +++ b/deps/sol2/examples/source/docs/simple_functions.cpp @@ -0,0 +1,18 @@ +#define SOL_ALL_SAFETIES_ON 1 + +#include +#include + +int main() { + sol::state lua; + int x = 0; + lua.set_function("beep", [&x]{ ++x; }); + lua.script("beep()"); + c_assert(x == 1); + + sol::function beep = lua["beep"]; + beep(); + c_assert(x == 2); + + return 0; +} diff --git a/deps/sol2/examples/source/docs/simple_structs.cpp b/deps/sol2/examples/source/docs/simple_structs.cpp new file mode 100644 index 0000000..9b0fc27 --- /dev/null +++ b/deps/sol2/examples/source/docs/simple_structs.cpp @@ -0,0 +1,32 @@ +#define SOL_ALL_SAFETIES_ON 1 + +#include +#include + +struct vars { + int boop = 0; + + int bop () const { + return boop + 1; + } +}; + +int main() { + sol::state lua; + lua.new_usertype("vars", + "boop", &vars::boop, + "bop", &vars::bop); + lua.script("beep = vars.new()\n" + "beep.boop = 1\n" + "bopvalue = beep:bop()"); + + vars& beep = lua["beep"]; + int bopvalue = lua["bopvalue"]; + + c_assert(beep.boop == 1); + c_assert(lua.get("beep").boop == 1); + c_assert(beep.bop() == 2); + c_assert(bopvalue == 2); + + return 0; +} diff --git a/deps/sol2/examples/source/docs/state_script_safe.cpp b/deps/sol2/examples/source/docs/state_script_safe.cpp new file mode 100644 index 0000000..22defee --- /dev/null +++ b/deps/sol2/examples/source/docs/state_script_safe.cpp @@ -0,0 +1,35 @@ +#define SOL_ALL_SAFETIES_ON 1 +#include + +#include + +int main () { + + std::cout << "=== safe_script usage ===" << std::endl; + + sol::state lua; + // uses sol::script_default_on_error, which either panics or throws, + // depending on your configuration and compiler settings + try { + auto result1 = lua.safe_script("bad.code"); + } + catch( const sol::error& e ) { + std::cout << "an expected error has occurred: " << e.what() << std::endl; + } + + // a custom handler that you write yourself + // is only called when an error happens with loading or running the script + auto result2 = lua.safe_script("123 bad.code", [](lua_State*, sol::protected_function_result pfr) { + // pfr will contain things that went wrong, for either loading or executing the script + // the user can do whatever they like here, including throw. Otherwise... + sol::error err = pfr; + std::cout << "An error (an expected one) occurred: " << err.what() << std::endl; + + // ... they need to return the protected_function_result + return pfr; + }); + + std::cout << std::endl; + + return 0; +} diff --git a/deps/sol2/examples/source/docs/state_transfer.cpp b/deps/sol2/examples/source/docs/state_transfer.cpp new file mode 100644 index 0000000..1728810 --- /dev/null +++ b/deps/sol2/examples/source/docs/state_transfer.cpp @@ -0,0 +1,48 @@ +#define SOL_ALL_SAFETIES_ON 1 + +#include + +#include +#include + +int main (int, char*[]) { + + sol::state lua; + lua.open_libraries(); + sol::function transferred_into; + lua["f"] = [&lua, &transferred_into](sol::object t, sol::this_state this_L) { + std::cout << "state of main : " << (void*)lua.lua_state() << std::endl; + std::cout << "state of function : " << (void*)this_L.lua_state() << std::endl; + // pass original lua_State* (or sol::state/sol::state_view) + // transfers ownership from the state of "t", + // to the "lua" sol::state + transferred_into = sol::function(lua, t); + }; + + lua.script(R"( + i = 0 + function test() + co = coroutine.create( + function() + local g = function() i = i + 1 end + f(g) + g = nil + collectgarbage() + end + ) + coroutine.resume(co) + co = nil + collectgarbage() + end + )"); + + // give it a try + lua.safe_script("test()"); + // should call 'g' from main thread, increment i by 1 + transferred_into(); + // check + int i = lua["i"]; + c_assert(i == 1); + + return 0; +} diff --git a/deps/sol2/examples/source/docs/std_thread.cpp b/deps/sol2/examples/source/docs/std_thread.cpp new file mode 100644 index 0000000..c610169 --- /dev/null +++ b/deps/sol2/examples/source/docs/std_thread.cpp @@ -0,0 +1,134 @@ +#define SOL_ALL_SAFETIES_ON 1 +#include + +#include +#include +#include +#include +#include +#include + +struct worker_data { + std::mutex until_ready_mutex; + std::condition_variable until_ready_condition; + bool is_ready = false; + bool is_processed = false; + sol::state worker_lua; + sol::bytecode payload; + std::variant> return_payload; + + worker_data() { + worker_lua.open_libraries(sol::lib::base); + } +}; + +void worker_thread(worker_data& data) { + for (std::uint64_t loops = 0; true; ++loops) { + // Wait until main() sends data + std::unique_lock data_lock(data.until_ready_mutex); + data.until_ready_condition.wait(data_lock, [&data] { return data.is_ready; }); + + if (data.payload.size() == 0) { + // signaling we are done + return; + } + + // just for easier typing + sol::state& lua = data.worker_lua; + + // we own the lock now, do the work + std::variant> result = lua.safe_script(data.payload.as_string_view()); + + // store returning payload, + // clear current payload + data.return_payload = std::move(result); + data.payload.clear(); + + // Send result back to main + std::cout << "worker_thread data processing is completed: signaling & unlocking\n"; + data.is_processed = true; + data.is_ready = false; + data_lock.unlock(); + data.until_ready_condition.notify_one(); + } +} + +int main() { + + // main lua state + sol::state lua; + lua.open_libraries(sol::lib::base); + + // set up functions, etc. etc. + lua.script("function f () return 4.5 end"); + lua.script("function g () return { 1.1, 2.2, 3.3 } end"); + + // kick off worker + worker_data data; + std::thread worker(worker_thread, std::ref(data)); + + // main Lua state + bool done_working = false; + for (std::uint64_t loops = 0; !done_working; ++loops) { + // finished working? send nothing + // even loop? use f + // otherwise, use g + if (loops >= 3) { + data.payload.clear(); + done_working = true; + } + else if ((loops % 2) == 0) { + sol::function target = lua["f"]; + data.payload = target.dump(); + } + else { + sol::function target = lua["g"]; + data.payload = target.dump(); + } + + // send data to the worker thread + { + std::lock_guard lk(data.until_ready_mutex); + data.is_ready = true; + std::cout << "function serialized: sending to worker thread to execute on Lua state...\n"; + } + data.until_ready_condition.notify_one(); + + if (done_working) { + break; + } + // wait for the worker + { + std::unique_lock lock_waiting_for_worker(data.until_ready_mutex); + data.until_ready_condition.wait(lock_waiting_for_worker, [&data] { return data.is_processed; }); + data.is_processed = false; + } + auto data_processor = [](auto& returned_data) { + using option_type = std::remove_cv_t>; + if constexpr (std::is_same_v) { + std::cout << "received a double: " << returned_data << "\n"; + } + else if constexpr (std::is_same_v>) { + std::cout << "received a std::vector: { "; + for (std::size_t i = 0; i < returned_data.size(); ++i) { + std::cout << returned_data[i]; + if (i != static_cast(returned_data.size() - 1)) { + std::cout << ", "; + } + } + std::cout << " }\n"; + } + else { + std::cerr << "OH MY GOD YOU FORGOT TO HANDLE A TYPE OF DATA FROM A WORKER ABORT ABORT ABORT\n"; + std::abort(); + } + }; + std::visit(data_processor, data.return_payload); + } + + // join and wait for workers to come back + worker.join(); + + // workers are back, exit program + return 0; +} -- cgit v1.2.3