lua-users home
lua-l archive

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


Slight side issue, in that if you are using ProDG PS2, the strtod, and atof
function is knackered!
(This was the problem we had)

-----Original Message-----
From: Chris Chapman [mailto:Chris.chapman@visentertainment.com] 
Sent: 24 October 2003 10:51
To: 'Lua list'
Subject: RE: Lua on the PlayStation2


I should perhaps have made the implementation a bit clearer: we only use Lua
in a very light sense, and most of the data storage/management is done in C
rather than in Lua. We store the references in a managed array of pending
function calls, limiting them to more than 10 outstanding at once. The
storage code is all properly checked and the data is sensible (since there
are never more than 2 outstanding pending functions at once). 

But the problem isn't occurring at the C level, it is the lua_*ref*
functions that are returning odd data. The grepped output from from my run
looks like:

lua_ref : 3
lua_getref : 3
lua_ref : 3
lua_unref : 3
lua_getref : 3

So at each call to the lua functions I output the reference that was
used/returned. The reference is not -1, so I'm not referencing nil, and
there are no other calls to luaL_ref or luaL_unref (from placing breakpoints
in the lua source). Tracing through the luaL_ref function takes the exact
same path both times, and the calls inside all return the same data both
calls. Could the lua_getref call somehow be unreferencing the data
indirectly?

As the post below shows, I can probably work around it by unreferencing the
first function before calling it, but it is awkward because my unref wrapper
function is seperate from my call wrapper function - i.e. I have to put the
unref code inside the call function so the unref occurs after the getref. At
the moment they are nice and cleanly seperate - I can call several times
without having to unref if I want to.

-----Original Message-----
From: RLake@oxfam.org.pe [mailto:RLake@oxfam.org.pe]
Sent: 23 October 2003 19:26
To: Chris.chapman@visentertainment.com
Subject: RE: Lua on the PlayStation2


Hi, Chris.

> But I'm tracking down a sneaky bug that was introduced with the 
> change.
We
> implement a 'pending-function' interface to our scripts which allows 
> us
to
> store a function with some parameters for calling at a later time 
> (after
the
> script which stored it has finished and returned control to the game 
> engine). We implemented this in Lua 4.0.1 by calling lua_ref(L, true) 
> to pull a reference to the function and lock it so it doesn't 
> accidentally
get
> garbage collected. To call the function, the game engine uses the
reference
> by calling lua_getref, calls the pending function, and then calls
lua_unref
> to clean up.

Maybe I'm being dense here, but I don't understand the details of your
implementation. Where does the reference get stored? Presumably in some game
engine data structure, or possibly in a per-script data structure? How does
the game engine deal with the case where there is already a stored
pending-reference, and a script tries to install another one? Perhaps you
have some bug there...

In any event, you seem to have the sequence:

  lua_getref(L, pref);
  lua_call(L, 0, 0);  // or pcall with arguments and results, maybe
  lua_unref(L, pref);

However, you could just as well do:

  lua_getref(L, pref);
  lua_unref(L, pref);
  lua_call(L, 0, 0);  // or pcall with arguments and results, maybe

After the call to getref, the function object is on the stack and will not
be garbage collectable until it is popped from the stack, and that certainly
won't happen while the function is being called. So that might simplify
handling of multiple pending-references.

There is nothing magical about the Lua registry. You could store your
pending functions in any Lua table, using any mechanism you liked. Normally,
it is pretty easy to do a queue in Lua, but if lua_Numbers are
single-precision in your implementation, you have to be careful to not
overflow the index.

-- This works fine with doubles; it can handle about 2^52 inserts
-- I'm assuming you won't have a lot of them, so I didn't muck
-- about with metamethods

function Queue(...)
  local low, high = 1, arg.n + 1

  function arg.put(obj)
    arg[high], high = obj, high + 1
    return arg
  end

  function arg.get()
    if low < high then
      local rv
      low, rv, arg[low] = low + 1, arg[low], nil
      return rv
    end
  end

  return arg
end

-- Example: flat traverse of a directory table; assume that
-- the keys are all strings.

-- I wrote it in functional style to demonstrate the use of
-- pending functions.

function dirlist(t, name)
  local done, workq = {}
  local function traverse(prefix, t)
    done[t] = true
    io.write("\n", prefix, ":")
    for k, v in t do
      io.write("\t", k)
      if type(v) == "table" then
        io.write "/"
        if done[v] then
          io.write "*"
         else
          local pfx, vv = prefix.."/"..k, v
          workq.put(function() traverse(pfx, vv) end)
        end
      end
    end
    io.write "\n"
  end
  workq = Queue(function() traverse(name or "", t) end)

  for fn in workq.get do fn() end
end

dirlist(getfenv(), ".")