update api, implement thread function arguments (so far)
This commit is contained in:
parent
5ffe3f958b
commit
8743ab21f7
@ -1,11 +1,6 @@
|
|||||||
--local thr = require('libbevy')
|
--local thr = require('libbevy')
|
||||||
package.cpath = package.cpath .. ";./?.dylib"
|
package.cpath = package.cpath .. ";./?.dylib" -- MAC OS support
|
||||||
require('libwoofer')
|
local api = require('libwoofer')
|
||||||
local thr = thread
|
api.thread.thread_id = nil
|
||||||
return {
|
api.thread.join = nil
|
||||||
new = function(func)
|
return api
|
||||||
local str_func = ("%q"):format(string.dump(func))
|
|
||||||
return thr.new(str_func)
|
|
||||||
end,
|
|
||||||
thread_id = thr.thread_id
|
|
||||||
}
|
|
||||||
42
src/lua-module.cpp
Normal file
42
src/lua-module.cpp
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
extern "C"
|
||||||
|
{
|
||||||
|
#include "lua.h"
|
||||||
|
#include "lauxlib.h"
|
||||||
|
#include "lualib.h"
|
||||||
|
}
|
||||||
|
|
||||||
|
#include "threading.h"
|
||||||
|
#include "shared-table.h"
|
||||||
|
|
||||||
|
sol::table core::init_state(sol::state_view& lua)
|
||||||
|
{
|
||||||
|
sol::usertype<LuaThread> thread_api(
|
||||||
|
sol::call_construction(), sol::constructors<sol::types<sol::function, sol::variadic_args>>(),
|
||||||
|
"join", &LuaThread::join,
|
||||||
|
"thread_id", &LuaThread::thread_id
|
||||||
|
);
|
||||||
|
sol::stack::push(lua, thread_api);
|
||||||
|
auto thread_obj = sol::stack::pop<sol::object>(lua);
|
||||||
|
|
||||||
|
sol::usertype<core::SharedTable> share_api(
|
||||||
|
sol::call_construction(), sol::default_constructor,
|
||||||
|
sol::meta_function::new_index, &core::SharedTable::luaSet,
|
||||||
|
sol::meta_function::index, &core::SharedTable::luaGet
|
||||||
|
);
|
||||||
|
sol::stack::push(lua, share_api);
|
||||||
|
auto share_obj = sol::stack::pop<sol::object>(lua);
|
||||||
|
|
||||||
|
sol::table public_api = lua.create_table_with(
|
||||||
|
"thread", thread_obj,
|
||||||
|
"share", share_obj
|
||||||
|
);
|
||||||
|
return public_api;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" int luaopen_libwoofer(lua_State *L)
|
||||||
|
{
|
||||||
|
sol::state_view lua(L);
|
||||||
|
sol::stack::push(lua, core::init_state(lua));
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
@ -11,6 +11,8 @@
|
|||||||
|
|
||||||
namespace core {
|
namespace core {
|
||||||
|
|
||||||
|
sol::table init_state(sol::state_view& lua);
|
||||||
|
|
||||||
class SharedTable {
|
class SharedTable {
|
||||||
public:
|
public:
|
||||||
SharedTable() = default;
|
SharedTable() = default;
|
||||||
@ -50,4 +52,4 @@ private:
|
|||||||
|
|
||||||
TablePool& defaultPool() noexcept;
|
TablePool& defaultPool() noexcept;
|
||||||
|
|
||||||
} // core
|
} // core
|
||||||
|
|||||||
@ -4,22 +4,11 @@
|
|||||||
|
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <iostream>
|
|
||||||
|
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
|
||||||
#define ERROR std::cerr
|
|
||||||
|
|
||||||
namespace core {
|
namespace core {
|
||||||
|
|
||||||
FunctionHolder::FunctionHolder(sol::stack_object luaObject) noexcept {
|
|
||||||
sol::state_view lua(luaObject.lua_state());
|
|
||||||
sol::function dumper = lua["string"]["dump"];
|
|
||||||
|
|
||||||
assert(dumper.valid());
|
|
||||||
function_ = dumper(luaObject);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool FunctionHolder::rawCompare(const BaseHolder* other) const noexcept {
|
bool FunctionHolder::rawCompare(const BaseHolder* other) const noexcept {
|
||||||
return function_ == static_cast<const FunctionHolder*>(other)->function_;
|
return function_ == static_cast<const FunctionHolder*>(other)->function_;
|
||||||
}
|
}
|
||||||
@ -49,31 +38,6 @@ sol::object FunctionHolder::unpack(sol::this_state state) const noexcept {
|
|||||||
StoredObject::StoredObject(StoredObject&& init) noexcept
|
StoredObject::StoredObject(StoredObject&& init) noexcept
|
||||||
: data_(std::move(init.data_)) {}
|
: data_(std::move(init.data_)) {}
|
||||||
|
|
||||||
StoredObject::StoredObject(sol::stack_object luaObject) noexcept
|
|
||||||
: data_(nullptr) {
|
|
||||||
switch(luaObject.get_type()) {
|
|
||||||
case sol::type::nil:
|
|
||||||
break;
|
|
||||||
case sol::type::boolean:
|
|
||||||
data_.reset(new PrimitiveHolder<bool>(luaObject));
|
|
||||||
break;
|
|
||||||
case sol::type::number:
|
|
||||||
data_.reset(new PrimitiveHolder<double>(luaObject));
|
|
||||||
break;
|
|
||||||
case sol::type::string:
|
|
||||||
data_.reset(new PrimitiveHolder<std::string>(luaObject));
|
|
||||||
break;
|
|
||||||
case sol::type::userdata:
|
|
||||||
data_.reset(new PrimitiveHolder<SharedTable*>(luaObject));
|
|
||||||
break;
|
|
||||||
case sol::type::function:
|
|
||||||
data_.reset(new FunctionHolder(luaObject));
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
ERROR << "Unable to store object of that type: " << (int)luaObject.get_type() << std::endl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
StoredObject::operator bool() const noexcept {
|
StoredObject::operator bool() const noexcept {
|
||||||
return (bool)data_;
|
return (bool)data_;
|
||||||
}
|
}
|
||||||
@ -115,4 +79,4 @@ bool StoredObject::operator<(const StoredObject& o) const noexcept {
|
|||||||
return data_.get() < o.data_.get();
|
return data_.get() < o.data_.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
} // core
|
} // core
|
||||||
|
|||||||
@ -3,9 +3,12 @@
|
|||||||
#include <sol.hpp>
|
#include <sol.hpp>
|
||||||
|
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
namespace core {
|
namespace core {
|
||||||
|
|
||||||
|
#define ERROR std::cerr
|
||||||
|
|
||||||
class BaseHolder {
|
class BaseHolder {
|
||||||
public:
|
public:
|
||||||
BaseHolder() noexcept : type_(sol::type::nil) {}
|
BaseHolder() noexcept : type_(sol::type::nil) {}
|
||||||
@ -41,8 +44,10 @@ template<typename StoredType>
|
|||||||
class PrimitiveHolder : public BaseHolder {
|
class PrimitiveHolder : public BaseHolder {
|
||||||
public:
|
public:
|
||||||
PrimitiveHolder(sol::stack_object luaObject) noexcept
|
PrimitiveHolder(sol::stack_object luaObject) noexcept
|
||||||
: data_(luaObject.as<StoredType>()) {
|
: data_(luaObject.as<StoredType>()) {}
|
||||||
}
|
|
||||||
|
PrimitiveHolder(sol::object luaObject) noexcept
|
||||||
|
: data_(luaObject.as<StoredType>()) {}
|
||||||
|
|
||||||
PrimitiveHolder(const StoredType& init) noexcept
|
PrimitiveHolder(const StoredType& init) noexcept
|
||||||
: data_(init) {}
|
: data_(init) {}
|
||||||
@ -71,7 +76,15 @@ private:
|
|||||||
|
|
||||||
class FunctionHolder : public BaseHolder {
|
class FunctionHolder : public BaseHolder {
|
||||||
public:
|
public:
|
||||||
FunctionHolder(sol::stack_object luaObject) noexcept;
|
template<typename SolObject>
|
||||||
|
FunctionHolder(SolObject luaObject) noexcept {
|
||||||
|
sol::state_view lua(luaObject.lua_state());
|
||||||
|
sol::function dumper = lua["string"]["dump"];
|
||||||
|
|
||||||
|
assert(dumper.valid());
|
||||||
|
function_ = dumper(luaObject);
|
||||||
|
}
|
||||||
|
|
||||||
bool rawCompare(const BaseHolder* other) const noexcept final;
|
bool rawCompare(const BaseHolder* other) const noexcept final;
|
||||||
bool rawLess(const BaseHolder* other) const noexcept final;
|
bool rawLess(const BaseHolder* other) const noexcept final;
|
||||||
std::size_t hash() const noexcept final;
|
std::size_t hash() const noexcept final;
|
||||||
@ -87,10 +100,34 @@ class StoredObject {
|
|||||||
public:
|
public:
|
||||||
StoredObject() = default;
|
StoredObject() = default;
|
||||||
StoredObject(StoredObject&& init) noexcept;
|
StoredObject(StoredObject&& init) noexcept;
|
||||||
StoredObject(sol::stack_object luaObject) noexcept;
|
|
||||||
//StoredObject(sol::object luaObject) noexcept;
|
|
||||||
StoredObject(SharedTable*) noexcept;
|
StoredObject(SharedTable*) noexcept;
|
||||||
|
|
||||||
|
template<typename SolObject>
|
||||||
|
StoredObject(SolObject luaObject)
|
||||||
|
{
|
||||||
|
switch(luaObject.get_type()) {
|
||||||
|
case sol::type::nil:
|
||||||
|
break;
|
||||||
|
case sol::type::boolean:
|
||||||
|
data_.reset(new PrimitiveHolder<bool>(luaObject));
|
||||||
|
break;
|
||||||
|
case sol::type::number:
|
||||||
|
data_.reset(new PrimitiveHolder<double>(luaObject));
|
||||||
|
break;
|
||||||
|
case sol::type::string:
|
||||||
|
data_.reset(new PrimitiveHolder<std::string>(luaObject));
|
||||||
|
break;
|
||||||
|
case sol::type::userdata:
|
||||||
|
data_.reset(new PrimitiveHolder<SharedTable*>(luaObject));
|
||||||
|
break;
|
||||||
|
case sol::type::function:
|
||||||
|
data_.reset(new FunctionHolder(luaObject));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
ERROR << "Unable to store object of that type: " << (int)luaObject.get_type() << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
operator bool() const noexcept;
|
operator bool() const noexcept;
|
||||||
std::size_t hash() const noexcept;
|
std::size_t hash() const noexcept;
|
||||||
sol::object unpack(sol::this_state state) const noexcept;
|
sol::object unpack(sol::this_state state) const noexcept;
|
||||||
@ -117,4 +154,4 @@ struct hash<core::StoredObject> {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
} // std
|
} // std
|
||||||
|
|||||||
@ -1,92 +1,66 @@
|
|||||||
extern "C"
|
#include "threading.h"
|
||||||
|
|
||||||
|
LuaThread::LuaThread(const sol::function& function, const sol::variadic_args& args) noexcept
|
||||||
{
|
{
|
||||||
#include "lua.h"
|
// 1. Dump function to string
|
||||||
#include "lauxlib.h"
|
sol::state_view lua(function.lua_state());
|
||||||
#include "lualib.h"
|
str_function_ = lua["string"]["dump"](function);
|
||||||
|
|
||||||
|
// 2. Create new state
|
||||||
|
p_state_.reset(new sol::state);
|
||||||
|
assert(p_state_.get() != NULL);
|
||||||
|
p_state_->open_libraries(
|
||||||
|
sol::lib::base, sol::lib::string,
|
||||||
|
sol::lib::package, sol::lib::io, sol::lib::os
|
||||||
|
);
|
||||||
|
auto thread_table = core::init_state(*p_state_);
|
||||||
|
(void)thread_table;
|
||||||
|
|
||||||
|
// 3. Save parameters
|
||||||
|
validate_args(args);
|
||||||
|
|
||||||
|
// 4. Run thread
|
||||||
|
p_thread_.reset(new std::thread(&LuaThread::work, this));
|
||||||
|
assert(p_thread_.get() != NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
#include <sol.hpp>
|
LuaThread::~LuaThread()
|
||||||
#include <iostream>
|
|
||||||
#include <sstream>
|
|
||||||
#include <thread>
|
|
||||||
|
|
||||||
#include "shared-table.h"
|
|
||||||
|
|
||||||
core::SharedTable shareTable;
|
|
||||||
|
|
||||||
class LuaThread
|
|
||||||
{
|
{
|
||||||
public:
|
join();
|
||||||
|
}
|
||||||
|
|
||||||
LuaThread(const std::string& rawFunction)
|
void LuaThread::validate_args(const sol::variadic_args& args) noexcept
|
||||||
: m_strFunction(rawFunction)
|
{
|
||||||
|
const auto end = --args.end();
|
||||||
|
for(auto iter = args.begin(); iter != end; iter++)
|
||||||
{
|
{
|
||||||
std::cout << "LuaThread" << std::endl;
|
core::StoredObject store(iter->get<sol::object>());
|
||||||
m_pState.reset(new sol::state);
|
arguments_.push_back(store.unpack(sol::this_state{p_state_->lua_state()}));
|
||||||
core::SharedTable::bind(*m_pState);
|
|
||||||
(*m_pState)["share"] = &shareTable;
|
|
||||||
assert(m_pState.get() != NULL);
|
|
||||||
m_pState->open_libraries(
|
|
||||||
sol::lib::base, sol::lib::string,
|
|
||||||
sol::lib::package, sol::lib::io, sol::lib::os
|
|
||||||
);
|
|
||||||
m_pThread.reset(new std::thread(&LuaThread::Impl, this));
|
|
||||||
assert(m_pThread.get() != NULL);
|
|
||||||
std::cout << "LuaThread##" << std::endl;
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
virtual ~LuaThread()
|
void LuaThread::join() noexcept
|
||||||
|
{
|
||||||
|
if (p_thread_.get())
|
||||||
{
|
{
|
||||||
std::cout << "~LuaThread" << std::endl;
|
p_thread_->join();
|
||||||
Join();
|
p_thread_.reset();
|
||||||
}
|
}
|
||||||
|
arguments_.clear();
|
||||||
|
if (p_state_.get())
|
||||||
|
p_state_.reset();
|
||||||
|
}
|
||||||
|
|
||||||
void Join()
|
void LuaThread::work() noexcept
|
||||||
{
|
{
|
||||||
std::cout << "Join started" << std::endl;
|
sol::state& lua = *p_state_;
|
||||||
if (m_pThread.get())
|
sol::function_result func = lua["loadstring"](str_function_);
|
||||||
{
|
func.get<sol::function>()(sol::as_args(arguments_));
|
||||||
m_pThread->join();
|
}
|
||||||
m_pThread.reset();
|
|
||||||
}
|
|
||||||
if (m_pState.get())
|
|
||||||
{
|
|
||||||
m_pState.reset();
|
|
||||||
}
|
|
||||||
std::cout << "Join finished" << std::endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
std::string LuaThread::thread_id() noexcept
|
||||||
void Impl()
|
|
||||||
{
|
|
||||||
std::cout << "Impl" << std::endl;
|
|
||||||
std::stringstream script;
|
|
||||||
script << "loadstring(" << m_strFunction << ")()";
|
|
||||||
m_pState->script(script.str());
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string m_strFunction;
|
|
||||||
std::shared_ptr<sol::state> m_pState;
|
|
||||||
std::shared_ptr<std::thread> m_pThread;
|
|
||||||
};
|
|
||||||
|
|
||||||
static std::string ThreadId()
|
|
||||||
{
|
{
|
||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
ss << std::hash<std::thread::id>()(std::this_thread::get_id());
|
ss << std::this_thread::get_id();
|
||||||
return ss.str();
|
return ss.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" int luaopen_libwoofer(lua_State *L)
|
|
||||||
{
|
|
||||||
sol::state_view lua(L);
|
|
||||||
lua.new_usertype<LuaThread>("thread",
|
|
||||||
sol::constructors<sol::types<std::string>>(),
|
|
||||||
"join", &LuaThread::Join
|
|
||||||
);
|
|
||||||
lua["thread"]["thread_id"] = ThreadId;
|
|
||||||
|
|
||||||
core::SharedTable::bind(lua);
|
|
||||||
lua["share"] = &shareTable;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|||||||
26
src/threading.h
Normal file
26
src/threading.h
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <sol.hpp>
|
||||||
|
#include <iostream>
|
||||||
|
#include <sstream>
|
||||||
|
#include <thread>
|
||||||
|
|
||||||
|
#include "shared-table.h"
|
||||||
|
|
||||||
|
class LuaThread
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
LuaThread(const sol::function& function, const sol::variadic_args& args) noexcept;
|
||||||
|
virtual ~LuaThread() noexcept;
|
||||||
|
void join() noexcept;
|
||||||
|
static std::string thread_id() noexcept;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void work() noexcept;
|
||||||
|
void validate_args(const sol::variadic_args& args) noexcept;
|
||||||
|
|
||||||
|
std::string str_function_;
|
||||||
|
std::shared_ptr<sol::state> p_state_;
|
||||||
|
std::shared_ptr<std::thread> p_thread_;
|
||||||
|
std::vector<sol::object> arguments_;
|
||||||
|
};
|
||||||
@ -1,95 +1,55 @@
|
|||||||
local thr = require('woofer')
|
function compare(o1, o2)
|
||||||
t = thr.new(
|
if o1 == o2 then return true end
|
||||||
function()
|
local o1Type = type(o1)
|
||||||
local thr = require('woofer')
|
local o2Type = type(o2)
|
||||||
print(share['key1'])
|
if o1Type ~= o2Type then return false end
|
||||||
print(share['key2'])
|
if o1Type ~= 'table' then return false end
|
||||||
print(share['key3'])
|
|
||||||
print(thr.thread_id())
|
local keySet = {}
|
||||||
for i = 1, 100 do
|
for key1, value1 in pairs(o1) do
|
||||||
io.write('2')
|
local value2 = o2[key1]
|
||||||
io.flush()
|
if value2 == nil or equals(value1, value2) == false then
|
||||||
os.execute("sleep 0.1")
|
return false
|
||||||
end
|
end
|
||||||
end
|
keySet[key1] = true
|
||||||
)
|
|
||||||
|
|
||||||
share['key1'] = 'val'
|
|
||||||
share['key2'] = 100500
|
|
||||||
share['key3'] = true
|
|
||||||
print(thr.thread_id())
|
|
||||||
for i = 1, 100 do
|
|
||||||
io.write('1')
|
|
||||||
io.flush()
|
|
||||||
os.execute("sleep 0.1")
|
|
||||||
end
|
|
||||||
t:join()
|
|
||||||
|
|
||||||
--[[
|
|
||||||
ppp("qwe")
|
|
||||||
t = thr.new(
|
|
||||||
function()
|
|
||||||
local thr = require('bevy')
|
|
||||||
print(("0x%x"):format(thr.thread_id()))
|
|
||||||
for i = 1, 10 do
|
|
||||||
io.write('.')
|
|
||||||
io.flush()
|
|
||||||
os.execute("sleep " .. 1)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
)
|
|
||||||
print(("0x%x"):format(thr.thread_id()))
|
|
||||||
|
|
||||||
for i = 1, 10 do
|
|
||||||
io.write(',')
|
|
||||||
io.flush()
|
|
||||||
os.execute("sleep " .. 1)
|
|
||||||
end
|
|
||||||
|
|
||||||
t:join()
|
|
||||||
|
|
||||||
print()
|
|
||||||
]]
|
|
||||||
|
|
||||||
--[[
|
|
||||||
str_foo = ""
|
|
||||||
|
|
||||||
asd =10
|
|
||||||
qwe = 20
|
|
||||||
function bar()
|
|
||||||
local lala = { 40 }
|
|
||||||
function foo(a, b)
|
|
||||||
local d = asd
|
|
||||||
local l = lala[1]
|
|
||||||
lala = 10
|
|
||||||
return function() return a + asd + b + qwe + l end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
print(debug.getupvalue(foo, 1))
|
for key2, _ in pairs(o2) do
|
||||||
print(debug.getupvalue(foo, 2))
|
if not keySet[key2] then return false end
|
||||||
table_print(debug.getinfo(foo))
|
end
|
||||||
str_foo = string.dump(foo)
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
bar()
|
function check(left, right)
|
||||||
|
if not compare(left, right) then
|
||||||
|
print("ERROR")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
foo2 = loadstring(str_foo)
|
-----------
|
||||||
|
-- TESTS --
|
||||||
|
-----------
|
||||||
|
|
||||||
|
do -- Simple smoke
|
||||||
|
package.cpath = package.cpath .. ";./?.dylib" -- MAC OS support
|
||||||
|
local woofer = require('libwoofer')
|
||||||
|
local share = woofer.share()
|
||||||
|
|
||||||
local t = {}
|
share["number"] = 100500
|
||||||
setmetatable(t,
|
share["string"] = "string value"
|
||||||
{
|
share["bool"] = true
|
||||||
__index = function(self, key)
|
|
||||||
print("Call ", key)
|
local thread = woofer.thread(
|
||||||
return _ENV[key]
|
function(share)
|
||||||
|
share["child.number"] = share["number"]
|
||||||
|
share["child.string"] = share["string"]
|
||||||
|
share["child.bool"] = share["bool"]
|
||||||
end,
|
end,
|
||||||
__newindex = function(self, key, value)
|
share
|
||||||
print("Call ", key, value)
|
)
|
||||||
_ENV[key] = value
|
thread:join()
|
||||||
end
|
|
||||||
}
|
check(share["child.number"], share["number"])
|
||||||
)
|
check(share["child.string"], share["string"])
|
||||||
debug.setupvalue(foo2, 1, t)
|
check(share["child.bool"], share["bool"])
|
||||||
debug.setupvalue(foo2, 2, { 99 })
|
end
|
||||||
print(foo2(10, 20)())
|
|
||||||
]]
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user