Get rid of effil.lua and allow to capture api in upvalue (#107)
This commit is contained in:
parent
8954dbe115
commit
d189d67349
@ -44,12 +44,12 @@ add_library(effil SHARED ${SOURCES})
|
|||||||
target_link_libraries(effil ${LUA_LIBRARY})
|
target_link_libraries(effil ${LUA_LIBRARY})
|
||||||
if (WIN32)
|
if (WIN32)
|
||||||
set_target_properties(effil PROPERTIES
|
set_target_properties(effil PROPERTIES
|
||||||
PREFIX lib
|
PREFIX ""
|
||||||
SUFFIX .dll)
|
SUFFIX .dll)
|
||||||
else()
|
else()
|
||||||
target_link_libraries(effil -lpthread -ldl)
|
target_link_libraries(effil -lpthread -ldl)
|
||||||
set_target_properties(effil PROPERTIES
|
set_target_properties(effil PROPERTIES
|
||||||
PREFIX lib
|
PREFIX ""
|
||||||
SUFFIX .so)
|
SUFFIX .so)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
@ -66,10 +66,6 @@ endif()
|
|||||||
#----------
|
#----------
|
||||||
# INSTALL -
|
# INSTALL -
|
||||||
#----------
|
#----------
|
||||||
install(FILES src/lua/effil.lua
|
|
||||||
DESTINATION ${CMAKE_INSTALL_PREFIX}
|
|
||||||
PERMISSIONS OWNER_READ GROUP_READ WORLD_READ)
|
|
||||||
|
|
||||||
install(TARGETS effil
|
install(TARGETS effil
|
||||||
DESTINATION ${CMAKE_INSTALL_PREFIX}
|
DESTINATION ${CMAKE_INSTALL_PREFIX}
|
||||||
PERMISSIONS OWNER_READ GROUP_READ WORLD_READ)
|
PERMISSIONS OWNER_READ GROUP_READ WORLD_READ)
|
||||||
|
|||||||
@ -9,15 +9,6 @@ using namespace effil;
|
|||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
sol::object createThread(const sol::this_state& lua,
|
|
||||||
const std::string& path,
|
|
||||||
const std::string& cpath,
|
|
||||||
int step,
|
|
||||||
const sol::function& function,
|
|
||||||
const sol::variadic_args& args) {
|
|
||||||
return sol::make_object(lua, GC::instance().create<Thread>(path, cpath, step, function, args));
|
|
||||||
}
|
|
||||||
|
|
||||||
sol::object createTable(sol::this_state lua, const sol::optional<sol::object>& tbl) {
|
sol::object createTable(sol::this_state lua, const sol::optional<sol::object>& tbl) {
|
||||||
if (tbl)
|
if (tbl)
|
||||||
{
|
{
|
||||||
@ -34,41 +25,94 @@ sol::object createChannel(const sol::stack_object& capacity, sol::this_state lua
|
|||||||
|
|
||||||
SharedTable globalTable = GC::instance().create<SharedTable>();
|
SharedTable globalTable = GC::instance().create<SharedTable>();
|
||||||
|
|
||||||
std::string getLuaTypename(const sol::stack_object& obj)
|
std::string getLuaTypename(const sol::stack_object& obj) {
|
||||||
{
|
|
||||||
return luaTypename<>(obj);
|
return luaTypename<>(obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size_t luaSize(const sol::stack_object& obj) {
|
||||||
|
if (obj.is<SharedTable>())
|
||||||
|
return SharedTable::luaSize(obj);
|
||||||
|
else if (obj.is<Channel>())
|
||||||
|
return obj.as<Channel>().size();
|
||||||
|
|
||||||
|
throw effil::Exception() << "Unsupported type "
|
||||||
|
<< luaTypename(obj) << " for effil.size()";
|
||||||
|
}
|
||||||
|
|
||||||
|
sol::table luaThreadConfig(sol::this_state state, const sol::stack_object& obj) {
|
||||||
|
REQUIRE(obj.valid() && obj.get_type() == sol::type::function)
|
||||||
|
<< "bad argument #1 to 'effil.thread' (function expected, got "
|
||||||
|
<< luaTypename(obj) << ")";
|
||||||
|
|
||||||
|
auto lua = sol::state_view(state);
|
||||||
|
const sol::function func = obj.as<sol::function>();
|
||||||
|
|
||||||
|
auto config = lua.create_table_with(
|
||||||
|
"path", lua["package"]["path"],
|
||||||
|
"cpath", lua["package"]["cpath"],
|
||||||
|
"step", 200
|
||||||
|
);
|
||||||
|
|
||||||
|
auto meta = lua.create_table_with();
|
||||||
|
meta[sol::meta_function::call] = [func](sol::this_state lua,
|
||||||
|
const sol::stack_table& self, const sol::variadic_args& args)
|
||||||
|
{
|
||||||
|
return sol::make_object(lua, GC::instance().create<Thread>(
|
||||||
|
self["path"], self["cpath"], self["step"], func, args));
|
||||||
|
};
|
||||||
|
|
||||||
|
config[sol::metatable_key] = meta;
|
||||||
|
return config;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
extern "C"
|
extern "C"
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
__declspec(dllexport)
|
__declspec(dllexport)
|
||||||
#endif
|
#endif
|
||||||
int luaopen_libeffil(lua_State* L) {
|
int luaopen_effil(lua_State* L) {
|
||||||
sol::state_view lua(L);
|
sol::state_view lua(L);
|
||||||
Thread::exportAPI(lua);
|
Thread::exportAPI(lua);
|
||||||
SharedTable::exportAPI(lua);
|
SharedTable::exportAPI(lua);
|
||||||
Channel::exportAPI(lua);
|
Channel::exportAPI(lua);
|
||||||
sol::table publicApi = lua.create_table_with(
|
|
||||||
"thread", createThread,
|
const sol::table gcApi = GC::exportAPI(lua);
|
||||||
"thread_id", threadId,
|
const sol::object gLuaTable = sol::make_object(lua, globalTable);
|
||||||
"sleep", sleep,
|
|
||||||
"yield", yield,
|
const auto luaIndex = [gcApi, gLuaTable](
|
||||||
"table", createTable,
|
const sol::stack_object& obj, const std::string& key) -> sol::object
|
||||||
"rawset", SharedTable::luaRawSet,
|
{
|
||||||
"rawget", SharedTable::luaRawGet,
|
if (key == "G")
|
||||||
"table_size", SharedTable::luaSize,
|
return gLuaTable;
|
||||||
|
else if (key == "gc")
|
||||||
|
return gcApi;
|
||||||
|
else if (key == "version")
|
||||||
|
return sol::make_object(obj.lua_state(), "0.1.0");
|
||||||
|
return sol::nil;
|
||||||
|
};
|
||||||
|
|
||||||
|
sol::usertype<EffilApiMarker> type("new", sol::no_constructor,
|
||||||
|
"thread", luaThreadConfig,
|
||||||
|
"thread_id", threadId,
|
||||||
|
"sleep", sleep,
|
||||||
|
"yield", yield,
|
||||||
|
"table", createTable,
|
||||||
|
"rawset", SharedTable::luaRawSet,
|
||||||
|
"rawget", SharedTable::luaRawGet,
|
||||||
"setmetatable", SharedTable::luaSetMetatable,
|
"setmetatable", SharedTable::luaSetMetatable,
|
||||||
"getmetatable", SharedTable::luaGetMetatable,
|
"getmetatable", SharedTable::luaGetMetatable,
|
||||||
"G", sol::make_object(lua, globalTable),
|
"channel", createChannel,
|
||||||
"gc", GC::exportAPI(lua),
|
"type", getLuaTypename,
|
||||||
"channel", createChannel,
|
"pairs", SharedTable::globalLuaPairs,
|
||||||
"type", getLuaTypename,
|
"ipairs", SharedTable::globalLuaIPairs,
|
||||||
"pairs", SharedTable::globalLuaPairs,
|
"size", luaSize,
|
||||||
"ipairs", SharedTable::globalLuaIPairs,
|
"allow_table_upvalues", luaAllowTableUpvalues,
|
||||||
"allow_table_upvalues", luaAllowTableUpvalues
|
sol::meta_function::index, luaIndex
|
||||||
);
|
);
|
||||||
sol::stack::push(lua, publicApi);
|
|
||||||
|
sol::stack::push(lua, type);
|
||||||
|
sol::stack::pop<sol::object>(lua);
|
||||||
|
sol::stack::push(lua, EffilApiMarker());
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -15,6 +15,15 @@ namespace effil {
|
|||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
|
class ApiReferenceHolder : public BaseHolder {
|
||||||
|
public:
|
||||||
|
bool rawCompare(const BaseHolder*) const noexcept final { return true; }
|
||||||
|
sol::object unpack(sol::this_state lua) const final {
|
||||||
|
luaopen_effil(lua);
|
||||||
|
return sol::stack::pop<sol::object>(lua);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
class NilHolder : public BaseHolder {
|
class NilHolder : public BaseHolder {
|
||||||
public:
|
public:
|
||||||
bool rawCompare(const BaseHolder*) const noexcept final { return true; }
|
bool rawCompare(const BaseHolder*) const noexcept final { return true; }
|
||||||
@ -163,6 +172,8 @@ StoredObject fromSolObject(const SolObject& luaObject) {
|
|||||||
return std::make_unique<FunctionHolder>(luaObject);
|
return std::make_unique<FunctionHolder>(luaObject);
|
||||||
else if (luaObject.template is<Thread>())
|
else if (luaObject.template is<Thread>())
|
||||||
return std::make_unique<GCObjectHolder<Thread>>(luaObject);
|
return std::make_unique<GCObjectHolder<Thread>>(luaObject);
|
||||||
|
else if (luaObject.template is<EffilApiMarker>())
|
||||||
|
return std::make_unique<ApiReferenceHolder>();
|
||||||
else
|
else
|
||||||
throw Exception() << "Unable to store userdata object";
|
throw Exception() << "Unable to store userdata object";
|
||||||
case sol::type::function: {
|
case sol::type::function: {
|
||||||
|
|||||||
@ -7,6 +7,8 @@
|
|||||||
|
|
||||||
namespace effil {
|
namespace effil {
|
||||||
|
|
||||||
|
struct EffilApiMarker{};
|
||||||
|
|
||||||
// Represents an interface for lua type stored at C++ code
|
// Represents an interface for lua type stored at C++ code
|
||||||
class BaseHolder {
|
class BaseHolder {
|
||||||
public:
|
public:
|
||||||
|
|||||||
@ -16,6 +16,12 @@
|
|||||||
# define LUA_INDEX_TYPE lua_Number
|
# define LUA_INDEX_TYPE lua_Number
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
extern "C"
|
||||||
|
#ifdef _WIN32
|
||||||
|
__declspec(dllexport)
|
||||||
|
#endif
|
||||||
|
int luaopen_effil(lua_State* L);
|
||||||
|
|
||||||
namespace effil {
|
namespace effil {
|
||||||
|
|
||||||
class Exception : public sol::error {
|
class Exception : public sol::error {
|
||||||
|
|||||||
@ -1,56 +0,0 @@
|
|||||||
local capi = require 'libeffil'
|
|
||||||
|
|
||||||
local api = {
|
|
||||||
version = "0.1.0",
|
|
||||||
table = capi.table,
|
|
||||||
thread_id = capi.thread_id,
|
|
||||||
sleep = capi.sleep,
|
|
||||||
yield = capi.yield,
|
|
||||||
rawget = capi.rawget,
|
|
||||||
rawset = capi.rawset,
|
|
||||||
setmetatable = capi.setmetatable,
|
|
||||||
getmetatable = capi.getmetatable,
|
|
||||||
G = capi.G,
|
|
||||||
gc = capi.gc,
|
|
||||||
channel = capi.channel,
|
|
||||||
type = capi.type,
|
|
||||||
pairs = capi.pairs,
|
|
||||||
ipairs = capi.ipairs,
|
|
||||||
allow_table_upvalues = capi.allow_table_upvalues
|
|
||||||
}
|
|
||||||
|
|
||||||
api.size = function (something)
|
|
||||||
local t = api.type(something)
|
|
||||||
if t == "effil.table" then
|
|
||||||
return capi.table_size(something)
|
|
||||||
elseif t == "effil.channel" then
|
|
||||||
return something:size()
|
|
||||||
else
|
|
||||||
error("Unsupported type " .. t .. " for effil.size()")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local function run_thread(config, 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
|
|
||||||
-- step - who fast reacte on state changing
|
|
||||||
-- __call - run thread, can be invoked multiple times
|
|
||||||
api.thread = function (f)
|
|
||||||
if type(f) ~= "function" then
|
|
||||||
error("bad argument #1 to 'effil.thread' (function expected, got " .. capi.type(f) .. ")")
|
|
||||||
end
|
|
||||||
|
|
||||||
local thread_config = {
|
|
||||||
path = package.path,
|
|
||||||
cpath = package.cpath,
|
|
||||||
step = 200 }
|
|
||||||
setmetatable(thread_config, {__call = function(c, ...) return run_thread(c, f, ...) end})
|
|
||||||
return thread_config
|
|
||||||
end
|
|
||||||
|
|
||||||
return api
|
|
||||||
@ -1,5 +1,7 @@
|
|||||||
require "bootstrap-tests"
|
require "bootstrap-tests"
|
||||||
|
|
||||||
|
local effil = effil
|
||||||
|
|
||||||
test.thread.tear_down = default_tear_down
|
test.thread.tear_down = default_tear_down
|
||||||
|
|
||||||
test.thread.wait = function ()
|
test.thread.wait = function ()
|
||||||
@ -26,7 +28,7 @@ end
|
|||||||
|
|
||||||
test.thread.timed_get = function ()
|
test.thread.timed_get = function ()
|
||||||
local thread = effil.thread(function()
|
local thread = effil.thread(function()
|
||||||
require('effil').sleep(2)
|
effil.sleep(2)
|
||||||
return "-_-"
|
return "-_-"
|
||||||
end)()
|
end)()
|
||||||
test.is_nil(thread:get(1))
|
test.is_nil(thread:get(1))
|
||||||
@ -35,7 +37,7 @@ end
|
|||||||
|
|
||||||
test.thread.timed_get = function ()
|
test.thread.timed_get = function ()
|
||||||
local thread = effil.thread(function()
|
local thread = effil.thread(function()
|
||||||
require('effil').sleep(2)
|
effil.sleep(2)
|
||||||
return 8
|
return 8
|
||||||
end)()
|
end)()
|
||||||
|
|
||||||
@ -50,7 +52,7 @@ end
|
|||||||
|
|
||||||
test.thread.async_wait = function()
|
test.thread.async_wait = function()
|
||||||
local thread = effil.thread( function()
|
local thread = effil.thread( function()
|
||||||
require('effil').sleep(1)
|
effil.sleep(1)
|
||||||
end)()
|
end)()
|
||||||
|
|
||||||
local iter = 0
|
local iter = 0
|
||||||
@ -86,7 +88,7 @@ test.thread.cancel = function ()
|
|||||||
jit ~= nil and
|
jit ~= nil and
|
||||||
function()
|
function()
|
||||||
while true do
|
while true do
|
||||||
require("effil").yield()
|
effil.yield()
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
or
|
or
|
||||||
@ -218,7 +220,7 @@ end
|
|||||||
|
|
||||||
test.thread.timed_cancel = function ()
|
test.thread.timed_cancel = function ()
|
||||||
local thread = effil.thread(function()
|
local thread = effil.thread(function()
|
||||||
require("effil").sleep(4)
|
effil.sleep(4)
|
||||||
end)()
|
end)()
|
||||||
test.is_false(thread:cancel(100, "ms"))
|
test.is_false(thread:cancel(100, "ms"))
|
||||||
thread:wait()
|
thread:wait()
|
||||||
@ -283,7 +285,7 @@ test.this_thread.functions = function ()
|
|||||||
|
|
||||||
local thread_factory = effil.thread(
|
local thread_factory = effil.thread(
|
||||||
function(share)
|
function(share)
|
||||||
share["child.id"] = require('effil').thread_id()
|
share["child.id"] = effil.thread_id()
|
||||||
end
|
end
|
||||||
)
|
)
|
||||||
local thread = thread_factory(share)
|
local thread = thread_factory(share)
|
||||||
@ -297,12 +299,12 @@ end
|
|||||||
test.this_thread.cancel_with_yield = function ()
|
test.this_thread.cancel_with_yield = function ()
|
||||||
local share = effil.table()
|
local share = effil.table()
|
||||||
local spec = effil.thread(function (share)
|
local spec = effil.thread(function (share)
|
||||||
require('effil').sleep(1)
|
effil.sleep(1)
|
||||||
for i=1,10000 do
|
for i=1,10000 do
|
||||||
-- Just waiting
|
-- Just waiting
|
||||||
end
|
end
|
||||||
share.done = true
|
share.done = true
|
||||||
require("effil").yield()
|
effil.yield()
|
||||||
share.afet_yield = true
|
share.afet_yield = true
|
||||||
end)
|
end)
|
||||||
spec.step = 0
|
spec.step = 0
|
||||||
@ -318,7 +320,7 @@ test.this_thread.pause_with_yield = function ()
|
|||||||
local share = effil.table({stop = false})
|
local share = effil.table({stop = false})
|
||||||
local spec = effil.thread(function (share)
|
local spec = effil.thread(function (share)
|
||||||
while not share.stop do
|
while not share.stop do
|
||||||
require("effil").yield()
|
effil.yield()
|
||||||
end
|
end
|
||||||
share.done = true
|
share.done = true
|
||||||
return true
|
return true
|
||||||
@ -339,7 +341,7 @@ test.this_thread.pause_with_yield = function ()
|
|||||||
end
|
end
|
||||||
|
|
||||||
local function worker(cmd)
|
local function worker(cmd)
|
||||||
eff = require("effil")
|
eff = effil
|
||||||
while not cmd.need_to_stop do
|
while not cmd.need_to_stop do
|
||||||
eff.yield()
|
eff.yield()
|
||||||
end
|
end
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user