hold strong ref for returned objects (#91)

This commit is contained in:
mihacooper 2017-10-18 10:15:33 +03:00 committed by Ilia
parent 7b73a0e0d9
commit f77391baa5
4 changed files with 32 additions and 2 deletions

View File

@ -63,8 +63,10 @@ StoredArray Channel::pop(const sol::optional<int>& duration,
}
auto ret = data_->channel_.front();
for (const auto& obj: ret)
for (const auto& obj: ret) {
obj->holdStrongReference();
removeReference(obj->gcHandle());
}
data_->channel_.pop();
return ret;

View File

@ -97,6 +97,12 @@ public:
strongRef_ = sol::nullopt;
}
void holdStrongReference() override {
if (!strongRef_) {
strongRef_ = GC::instance().get<T>(handle_);
}
}
private:
GCObjectHandle handle_;
sol::optional<T> strongRef_;

View File

@ -24,6 +24,7 @@ public:
virtual sol::object unpack(sol::this_state state) const = 0;
virtual GCObjectHandle gcHandle() const { return GCNull; }
virtual void releaseStrongReference() { }
virtual void holdStrongReference() { }
private:
BaseHolder(const BaseHolder&) = delete;

View File

@ -68,4 +68,25 @@ if not os.getenv("APPVEYOR") then
test.equal(chan:pop(10), "hello!")
test.is_true(os.time() < start_time + 10)
end
end
end
-- regress for channel returns
test.channel_stress.retun_tables = function ()
local function worker()
local effil = require "effil"
local ch = effil.channel()
for i = 1, 1000 do
ch:push(effil.table())
local ret = { ch:pop() }
end
end
local threads = {}
for i = 1, 20 do
table.insert(threads, effil.thread(worker)())
end
for _, thr in ipairs(threads) do
thr:wait()
end
end