lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


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"))