summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Silverstone <daniel.silverstone@codethink.co.uk>2012-08-13 17:33:24 +0100
committerDaniel Silverstone <daniel.silverstone@codethink.co.uk>2012-08-13 17:33:24 +0100
commit54fe3def54132bf739f38cd77ad78a73aa6ad23b (patch)
tree164e84078c48ada8e8a280595f2f0971e9adf75d
parent6726163fef48df4c6ec3dde81d5f68d1d52c8e4d (diff)
downloadsupple-54fe3def54132bf739f38cd77ad78a73aa6ad23b.tar.gz
OBJECTS: Refcount tags (proxies) so that we only pass __gc across when we really mean itdiagnosis
-rw-r--r--lib/supple/objects.lua18
1 files 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