Cancel in yield 2 (#50)
This commit is contained in:
parent
265b12370b
commit
6b77d9f9ec
@ -24,7 +24,7 @@ endif()
|
|||||||
add_library(effil SHARED ${SOURCES})
|
add_library(effil SHARED ${SOURCES})
|
||||||
target_link_libraries(effil -lpthread ${LUA_LIBRARY})
|
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(ENABLE_WARNINGS "-Wall -Wextra -pedantic")
|
||||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${GENERAL} ${ENABLE_WARNINGS}")
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${GENERAL} ${ENABLE_WARNINGS}")
|
||||||
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -Werror -O0 -g -UNDEBUG")
|
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -Werror -O0 -g -UNDEBUG")
|
||||||
|
|||||||
@ -12,11 +12,10 @@ namespace {
|
|||||||
sol::object createThread(const sol::this_state& lua,
|
sol::object createThread(const sol::this_state& lua,
|
||||||
const std::string& path,
|
const std::string& path,
|
||||||
const std::string& cpath,
|
const std::string& cpath,
|
||||||
bool stepwise,
|
int step,
|
||||||
unsigned int step,
|
|
||||||
const sol::function& function,
|
const sol::function& function,
|
||||||
const sol::variadic_args& args) {
|
const sol::variadic_args& args) {
|
||||||
return sol::make_object(lua, std::make_shared<Thread>(path, cpath, stepwise, step, function, args));
|
return sol::make_object(lua, std::make_shared<Thread>(path, cpath, step, function, args));
|
||||||
}
|
}
|
||||||
|
|
||||||
sol::object createTable(sol::this_state lua) {
|
sol::object createTable(sol::this_state lua) {
|
||||||
|
|||||||
@ -49,11 +49,8 @@ enum class Command {
|
|||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
|
|
||||||
class ThreadHandle {
|
class ThreadHandle {
|
||||||
public:
|
public:
|
||||||
const bool managed;
|
|
||||||
|
|
||||||
Status status;
|
Status status;
|
||||||
StoredArray result;
|
StoredArray result;
|
||||||
|
|
||||||
@ -64,9 +61,8 @@ public:
|
|||||||
Notifier syncPause;
|
Notifier syncPause;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ThreadHandle(bool isManaged)
|
ThreadHandle()
|
||||||
: managed(isManaged)
|
: status(Status::Running)
|
||||||
, status(Status::Running)
|
|
||||||
, command_(Command::Run)
|
, command_(Command::Run)
|
||||||
, lua_(std::make_unique<sol::state>()) {
|
, lua_(std::make_unique<sol::state>()) {
|
||||||
luaL_openlibs(*lua_);
|
luaL_openlibs(*lua_);
|
||||||
@ -171,7 +167,11 @@ std::string threadId() {
|
|||||||
return ss.str();
|
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<int>& duration, const sol::optional<std::string>& period) {
|
void sleep(const sol::optional<int>& duration, const sol::optional<std::string>& period) {
|
||||||
if (duration)
|
if (duration)
|
||||||
@ -182,17 +182,16 @@ void sleep(const sol::optional<int>& duration, const sol::optional<std::string>&
|
|||||||
|
|
||||||
Thread::Thread(const std::string& path,
|
Thread::Thread(const std::string& path,
|
||||||
const std::string& cpath,
|
const std::string& cpath,
|
||||||
bool managed,
|
int step,
|
||||||
unsigned int step,
|
|
||||||
const sol::function& function,
|
const sol::function& function,
|
||||||
const sol::variadic_args& variadicArgs)
|
const sol::variadic_args& variadicArgs)
|
||||||
: handle_(std::make_shared<ThreadHandle>(managed)) {
|
: handle_(std::make_shared<ThreadHandle>()) {
|
||||||
|
|
||||||
handle_->lua()["package"]["path"] = path;
|
handle_->lua()["package"]["path"] = path;
|
||||||
handle_->lua()["package"]["cpath"] = cpath;
|
handle_->lua()["package"]["cpath"] = cpath;
|
||||||
handle_->lua().script("require 'effil'");
|
handle_->lua().script("require 'effil'");
|
||||||
|
|
||||||
if (managed)
|
if (step != 0)
|
||||||
lua_sethook(handle_->lua(), luaHook, LUA_MASKCOUNT, step);
|
lua_sethook(handle_->lua(), luaHook, LUA_MASKCOUNT, step);
|
||||||
|
|
||||||
std::string strFunction = dumpFunction(function);
|
std::string strFunction = dumpFunction(function);
|
||||||
@ -264,8 +263,6 @@ StoredArray Thread::get(const sol::optional<int>& duration,
|
|||||||
bool Thread::cancel(const sol::this_state&,
|
bool Thread::cancel(const sol::this_state&,
|
||||||
const sol::optional<int>& duration,
|
const sol::optional<int>& duration,
|
||||||
const sol::optional<std::string>& period) {
|
const sol::optional<std::string>& period) {
|
||||||
REQUIRE(handle_->managed) << "Unable to cancel: unmanaged thread";
|
|
||||||
|
|
||||||
handle_->command(Command::Cancel);
|
handle_->command(Command::Cancel);
|
||||||
handle_->pause.notify();
|
handle_->pause.notify();
|
||||||
|
|
||||||
@ -280,8 +277,6 @@ bool Thread::cancel(const sol::this_state&,
|
|||||||
bool Thread::pause(const sol::this_state&,
|
bool Thread::pause(const sol::this_state&,
|
||||||
const sol::optional<int>& duration,
|
const sol::optional<int>& duration,
|
||||||
const sol::optional<std::string>& period) {
|
const sol::optional<std::string>& period) {
|
||||||
REQUIRE(handle_->managed) << "Unable to pause: unmanaged thread";
|
|
||||||
|
|
||||||
handle_->pause.reset();
|
handle_->pause.reset();
|
||||||
handle_->command(Command::Pause);
|
handle_->command(Command::Pause);
|
||||||
|
|
||||||
@ -294,8 +289,6 @@ bool Thread::pause(const sol::this_state&,
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Thread::resume() {
|
void Thread::resume() {
|
||||||
REQUIRE(handle_->managed) << "Unable to resume: unmanaged thread";
|
|
||||||
|
|
||||||
handle_->command(Command::Run);
|
handle_->command(Command::Run);
|
||||||
handle_->syncPause.reset();
|
handle_->syncPause.reset();
|
||||||
handle_->pause.notify();
|
handle_->pause.notify();
|
||||||
|
|||||||
@ -16,8 +16,7 @@ class Thread {
|
|||||||
public:
|
public:
|
||||||
Thread(const std::string& path,
|
Thread(const std::string& path,
|
||||||
const std::string& cpath,
|
const std::string& cpath,
|
||||||
bool managed,
|
int step,
|
||||||
unsigned int step,
|
|
||||||
const sol::function& function,
|
const sol::function& function,
|
||||||
const sol::variadic_args& args);
|
const sol::variadic_args& args);
|
||||||
|
|
||||||
|
|||||||
@ -37,21 +37,19 @@ api.type = function (something)
|
|||||||
end
|
end
|
||||||
|
|
||||||
local function run_thread(config, f, ...)
|
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
|
end
|
||||||
|
|
||||||
-- Creates thread runner with given function
|
-- Creates thread runner with given function
|
||||||
-- configurable parameters:
|
-- configurable parameters:
|
||||||
-- path - lua modules search path in child thread
|
-- path - lua modules search path in child thread
|
||||||
-- cpath - lua libs search path in child thread
|
-- cpath - lua libs search path in child thread
|
||||||
-- stepwise - is thread resumable
|
|
||||||
-- step - who fast reacte on state changing
|
-- step - who fast reacte on state changing
|
||||||
-- __call - run thread, can be invoked multiple times
|
-- __call - run thread, can be invoked multiple times
|
||||||
api.thread = function (f)
|
api.thread = function (f)
|
||||||
local thread_config = {
|
local thread_config = {
|
||||||
path = package.path,
|
path = package.path,
|
||||||
cpath = package.cpath,
|
cpath = package.cpath,
|
||||||
managed = true,
|
|
||||||
step = 200 }
|
step = 200 }
|
||||||
setmetatable(thread_config, {__call = function(c, ...) return run_thread(c, f, ...) end})
|
setmetatable(thread_config, {__call = function(c, ...) return run_thread(c, f, ...) end})
|
||||||
return thread_config
|
return thread_config
|
||||||
|
|||||||
@ -279,5 +279,45 @@ test.this_thread.functions = function ()
|
|||||||
test.is_string(share["child.id"])
|
test.is_string(share["child.id"])
|
||||||
test.is_number(tonumber(share["child.id"]))
|
test.is_number(tonumber(share["child.id"]))
|
||||||
test.not_equal(share["child.id"], effil.thread_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
|
end
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user