[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
- Subject: question regarding the use of luaL_ref/luaL_unref to implement reference counting
- From: "Vijay Aswadhati" <wyseman@...>
- Date: Tue, 15 Jul 2003 07:13:51 -0700
As they say the devil is in the details! As mentioned
in a post few days back I have a working binding to an
simple "C" library that is nothing but a lookup table.
A sample code that illustrates the use of this binding
for Lua is given below for reference.
A simple code inspection (before I could post the binding
to the Wiki) revealed that the memory usage was not optimal
since, the keys and data had to be duplicated before they
could be stored in the native table and freed when the node
is removed. Duplicated because, Lua should have allocated
the memory for these as well.
So I maintained my own tables (k_table, d_table) in which I
store the key or data and return a fresh luaL_ref to it
only if it did not already exist in this table. And I store
the ref value in the native structure used by the lookup
algorithm to which I am creating the binding.
Such naive use of luaL_ref/luaL_unref did not take me anywhere
and I think I know why. It is because luaL_ref returns a
'fresh reference' to the datum independent of whether it has
already been luaL_ref'd or not.
Finally the question(s):
1) Is it worth implementing a reference counting scheme
to pin Lua objects so that they can be safely used
in the "C" code without worrying about the garbage
collector collecting such objects?
2) Has this already been done and is the source code to
it available?
3) A first pass attempt was to use luaL_ref/luaL_unref to
implement such a scheme. This is what I have in mind :
int ref_ref(lua_State *L, void *pool, int si);
returns the reference to the object on the
stack at index <si> in <pool>. <pool> is
really a lightuserdata index to an internal
table.
If the object does not exist in the <pool>
then it is added to the pool, a luaL_ref
value is associated and the reference count
to this newly added object is set to 1. The
newly luaL_refd value is returned.
If the object exists in the <pool>, then the
reference count is bumped up and the luaL_ref
value associated with this object is returned.
int ref_unref(lua_State *L, void *pool, int si);
returns a positive integer if the object on the
stack at index <si> in <pool> is removed from
the <pool>. <pool> is really a lightuserdata
index to an internal table.
If the object does not exist in the <pool> then this
is an error condition and a -1 is returned.
If the object exists in the <pool>, then the reference
count is reduced by 1.
If the reference count counts down to zero, then then
the object is luaL_unrefd, the record associated with
this object is 'nil'd and finally the function
returns 0. Otherwise the reference count is returned.
Any comments?
-- v.a
require"ldb"
------------------------------------------------------
print(ldb.version)
-- create a lookup db that uses the SPLAY data structure
-- internally and allow duplicate keys.
db=assert(ldb.create("SPLAY", true))
db:insert("JAN","January")
db:insert("FEB","February")
db:insert("JUL","July")
if db:duplicatesAllowed() then
print(db:insert("JUL","Julho"))
end
print"\n--- After inserting using db:insert()---------"
n=0
for entry in ldb.entries(db) do
n=n+1
print(n,entry:key(), entry:data())
end
-- lookup some key
print"\n--- Some basic operations---------------------"
dn = db:lookup("FEB")
print("key=", dn:key(), "data=", dn:data())
dn:data("Ferverio")
print("key=", dn:key(), "data=", dn:data())
db:remove(dn);
print ("lookup 'FEB' yields: ", db:lookup("FEB"))
db:insert("FEB", "February");
print ("lookup 'FEB' yields: ", db:lookup("FEB"))
if db:duplicatesAllowed() then
print(db:insert("JUL","Julho"))
end
print(db:insert("XXX","Julho"))
print("JUL is",db:lookup("JUL"))