update api, implement thread function arguments (so far)

This commit is contained in:
mihacooper 2017-01-19 01:32:29 +03:00
parent 5ffe3f958b
commit 8743ab21f7
8 changed files with 216 additions and 216 deletions

View File

@ -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
View 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;
}

View File

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

View File

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

View File

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

View File

@ -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
View 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_;
};

View File

@ -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)())
]]