diff --git a/CMakeLists.txt b/CMakeLists.txt index ceea478..4bfcce1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -24,7 +24,7 @@ endif() add_library(effil SHARED ${SOURCES}) target_link_libraries(effil -lpthread ${LUA_LIBRARY}) -set(GENERAL "-std=c++14") +set(GENERAL "-std=c++14 -DSOL_EXCEPTIONS_SAFE_PROPAGATION") set(ENABLE_WARNINGS "-Wall -Wextra -pedantic") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${GENERAL} ${ENABLE_WARNINGS}") set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -Werror -O0 -g -UNDEBUG") diff --git a/src/cpp/lua-module.cpp b/src/cpp/lua-module.cpp index a5ffa3d..7992f69 100644 --- a/src/cpp/lua-module.cpp +++ b/src/cpp/lua-module.cpp @@ -12,11 +12,10 @@ namespace { sol::object createThread(const sol::this_state& lua, const std::string& path, const std::string& cpath, - bool stepwise, - unsigned int step, + int step, const sol::function& function, const sol::variadic_args& args) { - return sol::make_object(lua, std::make_shared(path, cpath, stepwise, step, function, args)); + return sol::make_object(lua, std::make_shared(path, cpath, step, function, args)); } sol::object createTable(sol::this_state lua) { diff --git a/src/cpp/threading.cpp b/src/cpp/threading.cpp index fed4d2a..0136acd 100644 --- a/src/cpp/threading.cpp +++ b/src/cpp/threading.cpp @@ -49,11 +49,8 @@ enum class Command { } // namespace - class ThreadHandle { public: - const bool managed; - Status status; StoredArray result; @@ -64,9 +61,8 @@ public: Notifier syncPause; public: - ThreadHandle(bool isManaged) - : managed(isManaged) - , status(Status::Running) + ThreadHandle() + : status(Status::Running) , command_(Command::Run) , lua_(std::make_unique()) { luaL_openlibs(*lua_); @@ -171,7 +167,11 @@ std::string threadId() { return ss.str(); } -void yield() { std::this_thread::yield(); } +void yield() { + if (thisThreadHandle) + luaHook(nullptr, nullptr); + std::this_thread::yield(); +} void sleep(const sol::optional& duration, const sol::optional& period) { if (duration) @@ -182,17 +182,16 @@ void sleep(const sol::optional& duration, const sol::optional& Thread::Thread(const std::string& path, const std::string& cpath, - bool managed, - unsigned int step, + int step, const sol::function& function, const sol::variadic_args& variadicArgs) - : handle_(std::make_shared(managed)) { + : handle_(std::make_shared()) { handle_->lua()["package"]["path"] = path; handle_->lua()["package"]["cpath"] = cpath; handle_->lua().script("require 'effil'"); - if (managed) + if (step != 0) lua_sethook(handle_->lua(), luaHook, LUA_MASKCOUNT, step); std::string strFunction = dumpFunction(function); @@ -264,8 +263,6 @@ StoredArray Thread::get(const sol::optional& duration, bool Thread::cancel(const sol::this_state&, const sol::optional& duration, const sol::optional& period) { - REQUIRE(handle_->managed) << "Unable to cancel: unmanaged thread"; - handle_->command(Command::Cancel); handle_->pause.notify(); @@ -280,8 +277,6 @@ bool Thread::cancel(const sol::this_state&, bool Thread::pause(const sol::this_state&, const sol::optional& duration, const sol::optional& period) { - REQUIRE(handle_->managed) << "Unable to pause: unmanaged thread"; - handle_->pause.reset(); handle_->command(Command::Pause); @@ -294,8 +289,6 @@ bool Thread::pause(const sol::this_state&, } void Thread::resume() { - REQUIRE(handle_->managed) << "Unable to resume: unmanaged thread"; - handle_->command(Command::Run); handle_->syncPause.reset(); handle_->pause.notify(); diff --git a/src/cpp/threading.h b/src/cpp/threading.h index 697a40c..b4c4c86 100644 --- a/src/cpp/threading.h +++ b/src/cpp/threading.h @@ -16,8 +16,7 @@ class Thread { public: Thread(const std::string& path, const std::string& cpath, - bool managed, - unsigned int step, + int step, const sol::function& function, const sol::variadic_args& args); diff --git a/src/lua/effil.lua b/src/lua/effil.lua index ef29b86..6135301 100644 --- a/src/lua/effil.lua +++ b/src/lua/effil.lua @@ -37,21 +37,19 @@ api.type = function (something) end local function run_thread(config, f, ...) - return capi.thread(config.path, config.cpath, config.managed, config.step, f, ...) + return capi.thread(config.path, config.cpath, config.step, f, ...) end -- Creates thread runner with given function -- configurable parameters: -- path - lua modules search path in child thread -- cpath - lua libs search path in child thread --- stepwise - is thread resumable -- step - who fast reacte on state changing -- __call - run thread, can be invoked multiple times api.thread = function (f) local thread_config = { path = package.path, cpath = package.cpath, - managed = true, step = 200 } setmetatable(thread_config, {__call = function(c, ...) return run_thread(c, f, ...) end}) return thread_config diff --git a/tests/lua/thread.lua b/tests/lua/thread.lua index 3f79887..54aa513 100644 --- a/tests/lua/thread.lua +++ b/tests/lua/thread.lua @@ -279,5 +279,45 @@ test.this_thread.functions = function () test.is_string(share["child.id"]) test.is_number(tonumber(share["child.id"])) test.not_equal(share["child.id"], effil.thread_id()) - effil.yield() -- just call it +end + +test.this_thread.cancel_with_yield = function () + local share = effil.table() + local spec = effil.thread(function (share) + require('effil').sleep(1) + for i=1,10000 do + -- Just waiting + end + share.done = true + require("effil").yield() + share.afet_yield = true + end) + spec.step = 0 + local thr = spec(share) + + test.is_true(thr:cancel()) + test.equal(thr:status(), "canceled") + test.is_true(share.done) + test.is_nil(share.afet_yield) +end + +test.this_thread.pause_with_yield = function () + local share = effil.table() + local spec = effil.thread(function (share) + for i=1,10000 do + require("effil").yield() + end + share.done = true + return true + end) + spec.step = 0 + local thr = spec(share) + + thr:pause() + test.is_nil(share.done) + test.equal(thr:status(), "paused") + thr:resume() + + test.is_true(thr:get()) + test.is_true(share.done) end