From dc2493e7525bb7633f697ef10f72b72b46222249 Mon Sep 17 00:00:00 2001 From: Andy Belle-Isle Date: Fri, 30 Aug 2019 00:45:36 -0400 Subject: Forget what I said, I just need to change git attributes to mark for vendor --- lib/sol2/examples/source/docs/std_thread.cpp | 134 +++++++++++++++++++++++++++ 1 file changed, 134 insertions(+) create mode 100644 lib/sol2/examples/source/docs/std_thread.cpp (limited to 'lib/sol2/examples/source/docs/std_thread.cpp') diff --git a/lib/sol2/examples/source/docs/std_thread.cpp b/lib/sol2/examples/source/docs/std_thread.cpp new file mode 100644 index 0000000..c610169 --- /dev/null +++ b/lib/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