From 54fe3def54132bf739f38cd77ad78a73aa6ad23b Mon Sep 17 00:00:00 2001 From: Daniel Silverstone Date: Mon, 13 Aug 2012 17:33:24 +0100 Subject: OBJECTS: Refcount tags (proxies) so that we only pass __gc across when we really mean it --- lib/supple/objects.lua | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/lib/supple/objects.lua b/lib/supple/objects.lua index 72eaf9a..2f5da79 100644 --- a/lib/supple/objects.lua +++ b/lib/supple/objects.lua @@ -16,18 +16,18 @@ local track = require 'supple.track' local my_objects_by_obj = {} local my_objects_by_tag = {} +local my_objects_expn_by_tag = {} local my_name = "UNSET" local my_counter = 0 local their_objects_by_tag = setmetatable({}, { __mode="v" }) local their_objects_by_obj = setmetatable({}, { __mode="k" }) +local their_objects_refcnt = {} local proc_call = nil local type = capi.rawtype local function clean_down(call_other_end) track.enter("clean_down") - setmetatable(their_objects_by_tag, { __mode="v" }) - setmetatable(their_objects_by_obj, { __mode="k" }) -- And force a full GC gc "collect" gc "collect" @@ -39,6 +39,7 @@ local function clean_down(call_other_end) -- And forget all our local objects my_objects_by_obj = {} my_objects_by_tag = {} + my_objects_expn_by_tag = {} track.leave("clean_down") end @@ -92,13 +93,14 @@ local function give(obj, special_tag) local tag = my_objects_by_obj[obj] if tag then track.leave("give", "ours", tag) - return { tag = tag } + return my_objects_expn_by_tag[tag] end -- otherwise wrap it freshly for us and return that. local tag = new_tag(special_tag) local expn = capi.explain(obj, tag) my_objects_by_obj[obj] = tag my_objects_by_tag[tag] = obj + my_objects_expn_by_tag[tag] = expn track.leave("give", "ours, new", tag) return expn end @@ -131,9 +133,9 @@ local function receive(obj) assert(capi.type(proxy) == obj.type) their_objects_by_tag[tag] = proxy their_objects_by_obj[proxy] = tag + their_objects_refcnt[tag] = (their_objects_refcnt[tag] or 0) + 1 -- Fill out the metatable obj.methods = obj.methods or {} - obj.methods[#obj.methods+1] = "__gc" if obj.type == "function" then obj.methods[#obj.methods+1] = "__call" end @@ -152,6 +154,13 @@ local function receive(obj) end mt[name] = meta_func end + function mt:__gc() + their_objects_refcnt[tag] = their_objects_refcnt[tag] - 1 + if their_objects_refcnt[tag] == 0 then + their_objects_refcnt[tag] = nil + proc_call(tag, "__gc") + end + end -- And return the proxy object track.leave("receive", "theirs, new", tostring(proxy)) return proxy @@ -163,6 +172,7 @@ local function forget_mine(tag) assert(obj, "Trying to forget nil object: " .. tag) my_objects_by_tag[tag] = nil my_objects_by_obj[obj] = nil + my_objects_expn_by_tag[tag] = nil track.leave("forget_mine", tag) end -- cgit v1.2.1