parent
2333863a68
commit
925494e7d5
@ -209,6 +209,8 @@ Thread result: 3
|
|||||||
Effil allows to transmit data between threads (Lua interpreter states) using `effil.channel`, `effil.table` or directly as parameters of `effil.thread`.
|
Effil allows to transmit data between threads (Lua interpreter states) using `effil.channel`, `effil.table` or directly as parameters of `effil.thread`.
|
||||||
- Primitive types are transmitted 'as is' by copy: `nil`, `boolean`, `number`, `string`
|
- Primitive types are transmitted 'as is' by copy: `nil`, `boolean`, `number`, `string`
|
||||||
- Functions are dumped using [`lua_dump`](#https://www.lua.org/manual/5.3/manual.html#lua_dump). Upvalues are captured according to [the rules](#functions-upvalues).
|
- Functions are dumped using [`lua_dump`](#https://www.lua.org/manual/5.3/manual.html#lua_dump). Upvalues are captured according to [the rules](#functions-upvalues).
|
||||||
|
- C functions (for which `lua_iscfunction` returns true) are transmitted just by a pointer using `lua_tocfunction` (in original lua_State) and lua_pushcfunction (in new lua_State).
|
||||||
|
**caution**: in LuaJIT standard functions like tonumber are not real C function, so `lua_iscfunction` returns true but `lua_tocfunction` returns nullptr. Due to that we don't find way to transmit it between lua_States.
|
||||||
- **Userdata and Lua threads (coroutines)** are not supported.
|
- **Userdata and Lua threads (coroutines)** are not supported.
|
||||||
- Tables are serialized to `effil.table` recursively. So, any Lua table becomes `effil.table`. Table serialization may take a lot of time for big table. Thus, it's better to put data directly to `effil.table` avoiding a table serialization. Let's consider 2 examples:
|
- Tables are serialized to `effil.table` recursively. So, any Lua table becomes `effil.table`. Table serialization may take a lot of time for big table. Thus, it's better to put data directly to `effil.table` avoiding a table serialization. Let's consider 2 examples:
|
||||||
```Lua
|
```Lua
|
||||||
|
|||||||
@ -108,7 +108,6 @@ class FunctionHolder : public GCObjectHolder<Function> {
|
|||||||
public:
|
public:
|
||||||
template <typename SolType>
|
template <typename SolType>
|
||||||
FunctionHolder(const SolType& luaObject) : GCObjectHolder<Function>(luaObject) {}
|
FunctionHolder(const SolType& luaObject) : GCObjectHolder<Function>(luaObject) {}
|
||||||
FunctionHolder(GCHandle handle) : GCObjectHolder(handle) {}
|
|
||||||
|
|
||||||
sol::object unpack(sol::this_state state) const final {
|
sol::object unpack(sol::this_state state) const final {
|
||||||
return GC::instance().get<Function>(handle_).loadFunction(state);
|
return GC::instance().get<Function>(handle_).loadFunction(state);
|
||||||
@ -119,6 +118,29 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class CFunctionHolder : public BaseHolder {
|
||||||
|
public:
|
||||||
|
CFunctionHolder(sol::state_view state, int stack_index)
|
||||||
|
: BaseHolder()
|
||||||
|
{
|
||||||
|
cfunction_ = lua_tocfunction(state, stack_index);
|
||||||
|
REQUIRE(cfunction_ != nullptr) << "can't get C function pointer";
|
||||||
|
}
|
||||||
|
|
||||||
|
sol::object unpack(sol::this_state state) const final {
|
||||||
|
lua_pushcfunction(state, cfunction_);
|
||||||
|
return sol::stack::pop<sol::object>(state);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool rawCompare(const BaseHolder* other) const override {
|
||||||
|
const auto cfh = dynamic_cast<const CFunctionHolder*>(other);
|
||||||
|
return cfh && cfh->cfunction_ == cfunction_;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
lua_CFunction cfunction_;
|
||||||
|
};
|
||||||
|
|
||||||
void dumpTable(SharedTable& target, const sol::table& luaTable, SolTableToShared& visited);
|
void dumpTable(SharedTable& target, const sol::table& luaTable, SolTableToShared& visited);
|
||||||
|
|
||||||
StoredObject makeStoredObject(const sol::object& luaObject, SolTableToShared& visited) {
|
StoredObject makeStoredObject(const sol::object& luaObject, SolTableToShared& visited) {
|
||||||
@ -186,6 +208,11 @@ StoredObject fromSolObject(const SolObject& luaObject, SolTableToShared& visited
|
|||||||
else
|
else
|
||||||
throw Exception() << "Unable to store userdata object";
|
throw Exception() << "Unable to store userdata object";
|
||||||
case sol::type::function: {
|
case sol::type::function: {
|
||||||
|
{
|
||||||
|
auto poper = sol::stack::push_pop(luaObject);
|
||||||
|
if (lua_iscfunction(luaObject.lua_state(), -1))
|
||||||
|
return std::make_unique<CFunctionHolder>(luaObject.lua_state(), -1);
|
||||||
|
}
|
||||||
Function func = GC::instance().create<Function>(luaObject, visited);
|
Function func = GC::instance().create<Function>(luaObject, visited);
|
||||||
return std::make_unique<FunctionHolder>(func.handle());
|
return std::make_unique<FunctionHolder>(func.handle());
|
||||||
}
|
}
|
||||||
|
|||||||
43
tests/lua/function.lua
Normal file
43
tests/lua/function.lua
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
require "bootstrap-tests"
|
||||||
|
|
||||||
|
test.func.tear_down = default_tear_down
|
||||||
|
|
||||||
|
test.func.check_truly_c_functions_p = function(func)
|
||||||
|
test.equal(type(func), "function")
|
||||||
|
|
||||||
|
local t = effil.table()
|
||||||
|
local ret, _ = pcall(function() t["func"] = func end)
|
||||||
|
test.equal(ret, true)
|
||||||
|
end
|
||||||
|
|
||||||
|
test.func.check_truly_c_functions_p(coroutine.create)
|
||||||
|
test.func.check_truly_c_functions_p(effil.size)
|
||||||
|
|
||||||
|
test.func.check_tosting_c_functions = function()
|
||||||
|
local t = effil.table()
|
||||||
|
|
||||||
|
if jit then
|
||||||
|
-- in LuaJIT it's not real C function
|
||||||
|
local ret, msg = pcall(function() t["tostring"] = tostring end)
|
||||||
|
test.equal(ret, false)
|
||||||
|
test.equal(msg, "effil.table: can't get C function pointer")
|
||||||
|
else
|
||||||
|
t["tostring"] = tostring
|
||||||
|
|
||||||
|
if LUA_VERSION > 51 then
|
||||||
|
test.equal(t["tostring"], tostring)
|
||||||
|
else
|
||||||
|
test.not_equal(t["tostring"], tostring)
|
||||||
|
end -- LUA_VERSION > 51
|
||||||
|
|
||||||
|
test.equal(t["tostring"](123), tostring(123))
|
||||||
|
test.equal(effil.thread(function() return t["tostring"](123) end)():get(), tostring(123))
|
||||||
|
|
||||||
|
local foo = tostring
|
||||||
|
test.equal(foo, tostring)
|
||||||
|
test.equal(foo(123), tostring(123))
|
||||||
|
test.equal(effil.thread(function() return foo(123) end)():get(), tostring(123))
|
||||||
|
end -- jit
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
@ -1,6 +1,10 @@
|
|||||||
#!/usr/bin/env lua
|
#!/usr/bin/env lua
|
||||||
|
|
||||||
print("Using " .. _VERSION)
|
if jit then
|
||||||
|
print("Using LuaJIT")
|
||||||
|
else
|
||||||
|
print("Using " .. _VERSION)
|
||||||
|
end
|
||||||
|
|
||||||
local scripts_path = arg[0]:gsub("[\\/]run_tests", "")
|
local scripts_path = arg[0]:gsub("[\\/]run_tests", "")
|
||||||
local src_path = scripts_path .. "/../.."
|
local src_path = scripts_path .. "/../.."
|
||||||
@ -17,6 +21,7 @@ require "metatable"
|
|||||||
require "type_mismatch"
|
require "type_mismatch"
|
||||||
require "upvalues"
|
require "upvalues"
|
||||||
require "dump_table"
|
require "dump_table"
|
||||||
|
require "function"
|
||||||
|
|
||||||
if os.getenv("STRESS") then
|
if os.getenv("STRESS") then
|
||||||
require "channel-stress"
|
require "channel-stress"
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user