Cancel in yield 2 (#50)

This commit is contained in:
Ilia 2017-06-12 14:50:00 +03:00 committed by GitHub
parent 265b12370b
commit 6b77d9f9ec
6 changed files with 56 additions and 27 deletions

View File

@ -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")

View File

@ -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<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) {

View File

@ -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<sol::state>()) {
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<int>& duration, const sol::optional<std::string>& period) {
if (duration)
@ -182,17 +182,16 @@ void sleep(const sol::optional<int>& duration, const sol::optional<std::string>&
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<ThreadHandle>(managed)) {
: handle_(std::make_shared<ThreadHandle>()) {
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<int>& duration,
bool Thread::cancel(const sol::this_state&,
const sol::optional<int>& duration,
const sol::optional<std::string>& 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<int>& duration,
const sol::optional<std::string>& 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();

View File

@ -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);

View File

@ -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

View File

@ -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