Merge pull request #18 from loud-hound/iudalov/stored-object2
Rewrite StroredObject logic
This commit is contained in:
commit
9f5267e23b
@ -11,6 +11,8 @@ namespace effil {
|
||||
// Unique handle for all objects spawned from one object.
|
||||
typedef void* GCObjectHandle;
|
||||
|
||||
static const GCObjectHandle GCNull = nullptr;
|
||||
|
||||
// All effil objects that owned in lua code have to inherit this class.
|
||||
// This type o object can persist in multiple threads and in multiple lua states.
|
||||
// Child has to care about storing data and concurrent access.
|
||||
|
||||
@ -9,13 +9,11 @@ namespace effil {
|
||||
|
||||
SharedTable::SharedTable() noexcept
|
||||
: GCObject(),
|
||||
lock_(new SpinMutex()),
|
||||
data_(new std::unordered_map<StoredObject, StoredObject>()){
|
||||
data_(std::make_shared<SharedData>()) {
|
||||
}
|
||||
|
||||
SharedTable::SharedTable(const SharedTable& init) noexcept
|
||||
: GCObject(init),
|
||||
lock_(init.lock_),
|
||||
data_(init.data_) {
|
||||
}
|
||||
|
||||
@ -31,50 +29,50 @@ sol::object SharedTable::getUserType(sol::state_view &lua) noexcept {
|
||||
}
|
||||
|
||||
void SharedTable::set(StoredObject&& key, StoredObject&& value) noexcept {
|
||||
std::lock_guard<SpinMutex> g(*lock_);
|
||||
std::lock_guard<SpinMutex> g(data_->lock);
|
||||
|
||||
if (key.isGCObject()) refs_->insert(key.gcHandle());
|
||||
if (value.isGCObject()) refs_->insert(value.gcHandle());
|
||||
if (key->gcHandle()) refs_->insert(key->gcHandle());
|
||||
if (value->gcHandle()) refs_->insert(value->gcHandle());
|
||||
|
||||
(*data_)[std::move(key)] = std::move(value);
|
||||
data_->entries[std::move(key)] = std::move(value);
|
||||
}
|
||||
|
||||
void SharedTable::luaSet(const sol::stack_object& luaKey, const sol::stack_object& luaValue) {
|
||||
ASSERT(luaKey.valid()) << "Invalid table index";
|
||||
|
||||
StoredObject key(luaKey);
|
||||
StoredObject key = createStoredObject(luaKey);
|
||||
if (luaValue.get_type() == sol::type::nil) {
|
||||
std::lock_guard<SpinMutex> g(*lock_);
|
||||
std::lock_guard<SpinMutex> g(data_->lock);
|
||||
|
||||
// in this case object is not obligatory to own data
|
||||
auto it = (*data_).find(key);
|
||||
if (it != (*data_).end()) {
|
||||
if (it->first.isGCObject()) refs_->erase(it->first.gcHandle());
|
||||
if (it->second.isGCObject()) refs_->erase(it->second.gcHandle());
|
||||
(*data_).erase(it);
|
||||
auto it = data_->entries.find(key);
|
||||
if (it != data_->entries.end()) {
|
||||
if (it->first->gcHandle()) refs_->erase(it->first->gcHandle());
|
||||
if (it->second->gcHandle()) refs_->erase(it->second->gcHandle());
|
||||
data_->entries.erase(it);
|
||||
}
|
||||
|
||||
} else {
|
||||
set(std::move(key), StoredObject(luaValue));
|
||||
set(std::move(key), createStoredObject(luaValue));
|
||||
}
|
||||
}
|
||||
|
||||
sol::object SharedTable::luaGet(const sol::stack_object& key, const sol::this_state& state) const {
|
||||
ASSERT(key.valid());
|
||||
|
||||
StoredObject cppKey(key);
|
||||
std::lock_guard<SpinMutex> g(*lock_);
|
||||
auto val = (*data_).find(cppKey);
|
||||
if (val == (*data_).end()) {
|
||||
StoredObject cppKey = createStoredObject(key);
|
||||
std::lock_guard<SpinMutex> g(data_->lock);
|
||||
auto val = data_->entries.find(cppKey);
|
||||
if (val == data_->entries.end()) {
|
||||
return sol::nil;
|
||||
} else {
|
||||
return val->second.unpack(state);
|
||||
return val->second->unpack(state);
|
||||
}
|
||||
}
|
||||
|
||||
size_t SharedTable::size() const noexcept {
|
||||
std::lock_guard<SpinMutex> g(*lock_);
|
||||
return data_->size();
|
||||
std::lock_guard<SpinMutex> g(data_->lock);
|
||||
return data_->entries.size();
|
||||
}
|
||||
|
||||
} // effil
|
||||
|
||||
@ -27,8 +27,14 @@ public:
|
||||
size_t size() const noexcept;
|
||||
|
||||
private:
|
||||
mutable std::shared_ptr<SpinMutex> lock_;
|
||||
std::shared_ptr<std::unordered_map<StoredObject, StoredObject>> data_;
|
||||
typedef std::unique_ptr<BaseHolder> StoredObject;
|
||||
struct SharedData {
|
||||
SpinMutex lock;
|
||||
std::unordered_map<StoredObject, StoredObject, StoredObjectHash, StoredObjectEqual> entries;
|
||||
};
|
||||
|
||||
private:
|
||||
std::shared_ptr<SharedData> data_;
|
||||
};
|
||||
|
||||
} // effil
|
||||
|
||||
@ -25,8 +25,8 @@ public:
|
||||
PrimitiveHolder(const StoredType& init) noexcept
|
||||
: data_(init) {}
|
||||
|
||||
bool compare(const BaseHolder* other) const noexcept final {
|
||||
return BaseHolder::compare(other) && static_cast<const PrimitiveHolder<StoredType>*>(other)->data_ == data_;
|
||||
bool rawCompare(const BaseHolder* other) const noexcept final {
|
||||
return static_cast<const PrimitiveHolder<StoredType>*>(other)->data_ == data_;
|
||||
}
|
||||
|
||||
std::size_t hash() const noexcept final {
|
||||
@ -51,8 +51,8 @@ public:
|
||||
function_ = dumper(luaObject);
|
||||
}
|
||||
|
||||
bool compare(const BaseHolder* other) const noexcept final {
|
||||
return BaseHolder::compare(other) && static_cast<const FunctionHolder*>(other)->function_ == function_;
|
||||
bool rawCompare(const BaseHolder* other) const noexcept final {
|
||||
return static_cast<const FunctionHolder*>(other)->function_ == function_;
|
||||
}
|
||||
|
||||
std::size_t hash() const noexcept final {
|
||||
@ -84,8 +84,8 @@ public:
|
||||
TableHolder(GCObjectHandle handle) noexcept
|
||||
: handle_(handle) {}
|
||||
|
||||
bool compare(const BaseHolder *other) const noexcept final {
|
||||
return BaseHolder::compare(other) && static_cast<const TableHolder*>(other)->handle_ == handle_;
|
||||
bool rawCompare(const BaseHolder *other) const noexcept final {
|
||||
return static_cast<const TableHolder*>(other)->handle_ == handle_;
|
||||
}
|
||||
|
||||
std::size_t hash() const noexcept final {
|
||||
@ -96,7 +96,7 @@ public:
|
||||
return sol::make_object(state, *static_cast<SharedTable*>(getGC().get(handle_)));
|
||||
}
|
||||
|
||||
GCObjectHandle handle() const noexcept { return handle_; }
|
||||
GCObjectHandle gcHandle() const noexcept override { return handle_; }
|
||||
private:
|
||||
GCObjectHandle handle_;
|
||||
};
|
||||
@ -120,12 +120,12 @@ StoredObject makeStoredObject(sol::object luaObject, SolTableToShared& visited)
|
||||
SharedTable table = getGC().create<SharedTable>();
|
||||
visited.emplace_back(std::make_pair(luaTable, table.handle()));
|
||||
dumpTable(&table, luaTable, visited);
|
||||
return StoredObject(table.handle());
|
||||
return createStoredObject(table.handle());
|
||||
} else {
|
||||
return StoredObject(st->second);
|
||||
return createStoredObject(st->second);
|
||||
}
|
||||
} else {
|
||||
return StoredObject(luaObject);
|
||||
return createStoredObject(luaObject);
|
||||
}
|
||||
}
|
||||
|
||||
@ -136,7 +136,7 @@ void dumpTable(SharedTable* target, sol::table luaTable, SolTableToShared& visit
|
||||
}
|
||||
|
||||
template<typename SolObject>
|
||||
std::unique_ptr<BaseHolder> fromSolObject(const SolObject& luaObject) {
|
||||
StoredObject fromSolObject(const SolObject& luaObject) {
|
||||
switch(luaObject.get_type()) {
|
||||
case sol::type::nil:
|
||||
break;
|
||||
@ -172,57 +172,28 @@ std::unique_ptr<BaseHolder> fromSolObject(const SolObject& luaObject) {
|
||||
|
||||
} // namespace
|
||||
|
||||
StoredObject::StoredObject(StoredObject&& init) noexcept
|
||||
: data_(std::move(init.data_)) {}
|
||||
|
||||
StoredObject::StoredObject(GCObjectHandle handle) noexcept
|
||||
: data_(new TableHolder(handle)) {
|
||||
StoredObject createStoredObject(bool value) {
|
||||
return std::make_unique<PrimitiveHolder<bool>>(value);
|
||||
}
|
||||
|
||||
StoredObject::StoredObject(const sol::object& object)
|
||||
: data_(fromSolObject(object)) {
|
||||
StoredObject createStoredObject(double value) {
|
||||
return std::make_unique<PrimitiveHolder<double>>(value);
|
||||
}
|
||||
|
||||
StoredObject::StoredObject(const sol::stack_object& object)
|
||||
: data_(fromSolObject(object)) {
|
||||
StoredObject createStoredObject(const std::string& value) {
|
||||
return std::make_unique<PrimitiveHolder<std::string>>(value);
|
||||
}
|
||||
|
||||
StoredObject::operator bool() const noexcept {
|
||||
return (bool)data_;
|
||||
StoredObject createStoredObject(const sol::object &object) {
|
||||
return fromSolObject(object);
|
||||
}
|
||||
|
||||
std::size_t StoredObject::hash() const noexcept {
|
||||
if (data_)
|
||||
return data_->hash();
|
||||
else
|
||||
return 0;
|
||||
StoredObject createStoredObject(const sol::stack_object &object) {
|
||||
return fromSolObject(object);
|
||||
}
|
||||
|
||||
sol::object StoredObject::unpack(sol::this_state state) const {
|
||||
if (data_)
|
||||
return data_->unpack(state);
|
||||
else
|
||||
return sol::nil;
|
||||
}
|
||||
|
||||
bool StoredObject::isGCObject() const noexcept {
|
||||
return data_->type() == typeid(TableHolder);
|
||||
}
|
||||
|
||||
GCObjectHandle StoredObject::gcHandle() const noexcept {
|
||||
return ((TableHolder*)data_.get())->handle();
|
||||
}
|
||||
|
||||
StoredObject& StoredObject::operator=(StoredObject&& o) noexcept {
|
||||
data_ = std::move(o.data_);
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool StoredObject::operator==(const StoredObject& o) const noexcept {
|
||||
if (data_ && o.data_)
|
||||
return data_->compare(o.data_.get());
|
||||
else
|
||||
return data_.get() == o.data_.get();
|
||||
StoredObject createStoredObject(GCObjectHandle handle) {
|
||||
return std::make_unique<TableHolder>(handle);
|
||||
}
|
||||
|
||||
} // effil
|
||||
|
||||
@ -11,54 +11,41 @@ public:
|
||||
BaseHolder() = default;
|
||||
virtual ~BaseHolder() = default;
|
||||
|
||||
virtual bool compare(const BaseHolder* other) const noexcept { return typeid(*this) == typeid(*other); }
|
||||
bool compare(const BaseHolder* other) const noexcept {
|
||||
return typeid(*this) == typeid(*other) && rawCompare(other);
|
||||
}
|
||||
virtual bool rawCompare(const BaseHolder* other) const = 0;
|
||||
virtual const std::type_info& type() { return typeid(*this); }
|
||||
|
||||
virtual std::size_t hash() const noexcept = 0;
|
||||
virtual sol::object unpack(sol::this_state state) const = 0;
|
||||
|
||||
virtual GCObjectHandle gcHandle() const noexcept { return GCNull; }
|
||||
|
||||
private:
|
||||
BaseHolder(const BaseHolder&) = delete;
|
||||
BaseHolder(BaseHolder&) = delete;
|
||||
};
|
||||
|
||||
class StoredObject {
|
||||
public:
|
||||
StoredObject() = default;
|
||||
StoredObject(StoredObject&& init) noexcept;
|
||||
StoredObject(GCObjectHandle) noexcept;
|
||||
StoredObject(const sol::object&);
|
||||
StoredObject(const sol::stack_object&);
|
||||
typedef std::unique_ptr<BaseHolder> StoredObject;
|
||||
|
||||
|
||||
operator bool() const noexcept;
|
||||
std::size_t hash() const noexcept;
|
||||
sol::object unpack(sol::this_state state) const;
|
||||
|
||||
bool isGCObject() const noexcept;
|
||||
GCObjectHandle gcHandle() const noexcept;
|
||||
|
||||
StoredObject& operator=(StoredObject&& o) noexcept;
|
||||
bool operator==(const StoredObject& o) const noexcept;
|
||||
|
||||
private:
|
||||
std::unique_ptr<BaseHolder> data_;
|
||||
|
||||
private:
|
||||
StoredObject(const StoredObject&) = delete;
|
||||
StoredObject& operator=(const StoredObject&) = delete;
|
||||
};
|
||||
|
||||
} // effil
|
||||
|
||||
namespace std {
|
||||
|
||||
// For storing as key in std::unordered_map
|
||||
template<>
|
||||
struct hash<effil::StoredObject> {
|
||||
std::size_t operator()(const effil::StoredObject &object) const noexcept {
|
||||
return object.hash();
|
||||
struct StoredObjectHash {
|
||||
size_t operator()(const StoredObject& o) const {
|
||||
return o->hash();
|
||||
}
|
||||
};
|
||||
|
||||
} // std
|
||||
struct StoredObjectEqual {
|
||||
bool operator()(const StoredObject& lhs, const StoredObject& rhs) const {
|
||||
return lhs->compare(rhs.get());
|
||||
}
|
||||
};
|
||||
|
||||
StoredObject createStoredObject(bool);
|
||||
StoredObject createStoredObject(double);
|
||||
StoredObject createStoredObject(const std::string&);
|
||||
StoredObject createStoredObject(GCObjectHandle);
|
||||
StoredObject createStoredObject(const sol::object &);
|
||||
StoredObject createStoredObject(const sol::stack_object &);
|
||||
|
||||
} // effil
|
||||
|
||||
@ -44,8 +44,8 @@ LuaThread::LuaThread(std::shared_ptr<ThreadData> threadData, const std::string&
|
||||
|
||||
std::vector<sol::object> arguments;
|
||||
for(const auto& iter: args) {
|
||||
StoredObject store(iter.get<sol::object>());
|
||||
arguments.push_back(store.unpack(sol::this_state{pThreadData_->luaState}));
|
||||
StoredObject store = createStoredObject(iter.get<sol::object>());
|
||||
arguments.push_back(store->unpack(sol::this_state{pThreadData_->luaState}));
|
||||
}
|
||||
|
||||
pThread_.reset(new std::thread(&LuaThread::work, pThreadData_, function, std::move(arguments)));
|
||||
@ -95,7 +95,7 @@ void LuaThread::work(std::shared_ptr<ThreadData> threadData, const std::string s
|
||||
(void)results; // TODO: try to avoid use of useless sol::function_result here
|
||||
sol::variadic_args args(threadData->luaState, -lua_gettop(threadData->luaState));
|
||||
for(const auto& iter: args) {
|
||||
StoredObject store(iter.get<sol::object>());
|
||||
StoredObject store = createStoredObject(iter.get<sol::object>());
|
||||
threadData->results.emplace_back(std::move(store));
|
||||
}
|
||||
threadData->status = ThreadStatus::Completed;
|
||||
@ -106,7 +106,7 @@ void LuaThread::work(std::shared_ptr<ThreadData> threadData, const std::string s
|
||||
catch (const sol::error& err) {
|
||||
threadData->status = ThreadStatus::Failed;
|
||||
sol::stack::push(threadData->luaState, err.what());
|
||||
StoredObject store(sol::stack::pop<sol::object>(threadData->luaState));
|
||||
StoredObject store = createStoredObject(sol::stack::pop<sol::object>(threadData->luaState));
|
||||
threadData->results.emplace_back(std::move(store));
|
||||
}
|
||||
}
|
||||
@ -139,7 +139,7 @@ std::tuple<sol::object, sol::table> LuaThread::wait(sol::this_state state) const
|
||||
{
|
||||
for (const StoredObject& obj: pThreadData_->results)
|
||||
{
|
||||
returns.add(obj.unpack(state));
|
||||
returns.add(obj->unpack(state));
|
||||
}
|
||||
}
|
||||
return std::make_tuple(sol::make_object(state, threadStatusToString(stat)), std::move(returns));
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user