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})
|
||||
if (WIN32)
|
||||
set_target_properties(effil PROPERTIES
|
||||
PREFIX lib
|
||||
PREFIX ""
|
||||
SUFFIX .dll)
|
||||
else()
|
||||
target_link_libraries(effil -lpthread -ldl)
|
||||
set_target_properties(effil PROPERTIES
|
||||
PREFIX lib
|
||||
PREFIX ""
|
||||
SUFFIX .so)
|
||||
endif()
|
||||
|
||||
@ -66,10 +66,6 @@ endif()
|
||||
#----------
|
||||
# INSTALL -
|
||||
#----------
|
||||
install(FILES src/lua/effil.lua
|
||||
DESTINATION ${CMAKE_INSTALL_PREFIX}
|
||||
PERMISSIONS OWNER_READ GROUP_READ WORLD_READ)
|
||||
|
||||
install(TARGETS effil
|
||||
DESTINATION ${CMAKE_INSTALL_PREFIX}
|
||||
PERMISSIONS OWNER_READ GROUP_READ WORLD_READ)
|
||||
|
||||
@ -9,15 +9,6 @@ using namespace effil;
|
||||
|
||||
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) {
|
||||
if (tbl)
|
||||
{
|
||||
@ -34,41 +25,94 @@ sol::object createChannel(const sol::stack_object& capacity, sol::this_state lua
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
extern "C"
|
||||
#ifdef _WIN32
|
||||
__declspec(dllexport)
|
||||
#endif
|
||||
int luaopen_libeffil(lua_State* L) {
|
||||
int luaopen_effil(lua_State* L) {
|
||||
sol::state_view lua(L);
|
||||
Thread::exportAPI(lua);
|
||||
SharedTable::exportAPI(lua);
|
||||
Channel::exportAPI(lua);
|
||||
sol::table publicApi = lua.create_table_with(
|
||||
"thread", createThread,
|
||||
|
||||
const sol::table gcApi = GC::exportAPI(lua);
|
||||
const sol::object gLuaTable = sol::make_object(lua, globalTable);
|
||||
|
||||
const auto luaIndex = [gcApi, gLuaTable](
|
||||
const sol::stack_object& obj, const std::string& key) -> sol::object
|
||||
{
|
||||
if (key == "G")
|
||||
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,
|
||||
"table_size", SharedTable::luaSize,
|
||||
"setmetatable", SharedTable::luaSetMetatable,
|
||||
"getmetatable", SharedTable::luaGetMetatable,
|
||||
"G", sol::make_object(lua, globalTable),
|
||||
"gc", GC::exportAPI(lua),
|
||||
"channel", createChannel,
|
||||
"type", getLuaTypename,
|
||||
"pairs", SharedTable::globalLuaPairs,
|
||||
"ipairs", SharedTable::globalLuaIPairs,
|
||||
"allow_table_upvalues", luaAllowTableUpvalues
|
||||
"size", luaSize,
|
||||
"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;
|
||||
}
|
||||
|
||||
@ -15,6 +15,15 @@ namespace effil {
|
||||
|
||||
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 {
|
||||
public:
|
||||
bool rawCompare(const BaseHolder*) const noexcept final { return true; }
|
||||
@ -163,6 +172,8 @@ StoredObject fromSolObject(const SolObject& luaObject) {
|
||||
return std::make_unique<FunctionHolder>(luaObject);
|
||||
else if (luaObject.template is<Thread>())
|
||||
return std::make_unique<GCObjectHolder<Thread>>(luaObject);
|
||||
else if (luaObject.template is<EffilApiMarker>())
|
||||
return std::make_unique<ApiReferenceHolder>();
|
||||
else
|
||||
throw Exception() << "Unable to store userdata object";
|
||||
case sol::type::function: {
|
||||
|
||||
@ -7,6 +7,8 @@
|
||||
|
||||
namespace effil {
|
||||
|
||||
struct EffilApiMarker{};
|
||||
|
||||
// Represents an interface for lua type stored at C++ code
|
||||
class BaseHolder {
|
||||
public:
|
||||
|
||||
@ -16,6 +16,12 @@
|
||||
# define LUA_INDEX_TYPE lua_Number
|
||||
#endif
|
||||
|
||||
extern "C"
|
||||
#ifdef _WIN32
|
||||
__declspec(dllexport)
|
||||
#endif
|
||||
int luaopen_effil(lua_State* L);
|
||||
|
||||
namespace effil {
|
||||
|
||||
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"
|
||||
|
||||
local effil = effil
|
||||
|
||||
test.thread.tear_down = default_tear_down
|
||||
|
||||
test.thread.wait = function ()
|
||||
@ -26,7 +28,7 @@ end
|
||||
|
||||
test.thread.timed_get = function ()
|
||||
local thread = effil.thread(function()
|
||||
require('effil').sleep(2)
|
||||
effil.sleep(2)
|
||||
return "-_-"
|
||||
end)()
|
||||
test.is_nil(thread:get(1))
|
||||
@ -35,7 +37,7 @@ end
|
||||
|
||||
test.thread.timed_get = function ()
|
||||
local thread = effil.thread(function()
|
||||
require('effil').sleep(2)
|
||||
effil.sleep(2)
|
||||
return 8
|
||||
end)()
|
||||
|
||||
@ -50,7 +52,7 @@ end
|
||||
|
||||
test.thread.async_wait = function()
|
||||
local thread = effil.thread( function()
|
||||
require('effil').sleep(1)
|
||||
effil.sleep(1)
|
||||
end)()
|
||||
|
||||
local iter = 0
|
||||
@ -86,7 +88,7 @@ test.thread.cancel = function ()
|
||||
jit ~= nil and
|
||||
function()
|
||||
while true do
|
||||
require("effil").yield()
|
||||
effil.yield()
|
||||
end
|
||||
end
|
||||
or
|
||||
@ -218,7 +220,7 @@ end
|
||||
|
||||
test.thread.timed_cancel = function ()
|
||||
local thread = effil.thread(function()
|
||||
require("effil").sleep(4)
|
||||
effil.sleep(4)
|
||||
end)()
|
||||
test.is_false(thread:cancel(100, "ms"))
|
||||
thread:wait()
|
||||
@ -283,7 +285,7 @@ test.this_thread.functions = function ()
|
||||
|
||||
local thread_factory = effil.thread(
|
||||
function(share)
|
||||
share["child.id"] = require('effil').thread_id()
|
||||
share["child.id"] = effil.thread_id()
|
||||
end
|
||||
)
|
||||
local thread = thread_factory(share)
|
||||
@ -297,12 +299,12 @@ end
|
||||
test.this_thread.cancel_with_yield = function ()
|
||||
local share = effil.table()
|
||||
local spec = effil.thread(function (share)
|
||||
require('effil').sleep(1)
|
||||
effil.sleep(1)
|
||||
for i=1,10000 do
|
||||
-- Just waiting
|
||||
end
|
||||
share.done = true
|
||||
require("effil").yield()
|
||||
effil.yield()
|
||||
share.afet_yield = true
|
||||
end)
|
||||
spec.step = 0
|
||||
@ -318,7 +320,7 @@ test.this_thread.pause_with_yield = function ()
|
||||
local share = effil.table({stop = false})
|
||||
local spec = effil.thread(function (share)
|
||||
while not share.stop do
|
||||
require("effil").yield()
|
||||
effil.yield()
|
||||
end
|
||||
share.done = true
|
||||
return true
|
||||
@ -339,7 +341,7 @@ test.this_thread.pause_with_yield = function ()
|
||||
end
|
||||
|
||||
local function worker(cmd)
|
||||
eff = require("effil")
|
||||
eff = effil
|
||||
while not cmd.need_to_stop do
|
||||
eff.yield()
|
||||
end
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user