lua-users home
lua-l archive

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


> Is that code thread safe? My read on this is that you are maintaining
> a single global table for dynamic variables.

It depends on what you mean by thread-safe, but probably not in the
sense you mean. It would be thread-safe if each thread had its own
dynamic variable table, though -- that would just mean initialising
the system in each thread (and giving each thread a separate globals
table, but I could work out a way around that if necessary.) I don't
much like threaded programming, fwiw, but I understand that I am in
a minority. Forking strikes me as a better model.

> I agree that searching the stack is not exactly speedy, but stacks
> aren't necessarily all that deep and my actual needs are akin to
> dynamic variables and could be implemented using them but aren't
> necessarily identical. (See my other message.)

OK, I thought you were searching out locals, which would be really
slow.

Here is kind of an outline solution which doesn't use tables at
all: (I don't have time to set up a test right now, so no guarantees
that it will even compile ... I do have a fully debugged version of
this on another computer, so if you want to use it and run into
trouble, let me know.)


-- This is the function you use to open a file from an accumulated
-- path. The initial value simply returns an error

function pathopen(filename) error("'"..filename.."' not found") end

-- path must end with a path separator (/ or \). This probably could
-- do a lot more sanity checking.

-- This is effectively a recursively traversed linked list
-- implemented with function closures:

local function putpath(p, path)
  return function(filename)
    return io.open(path..filename) or p(filename)
  end
end

-- This function brackets a chunk with local definitions
-- of pathopen and loadwithpath; the chunk becomes a function
-- which returns the original chunk. 

-- For simplicity, I assume that the path to the chunk has already
-- been split into directory and filename parts

-- The functions get deeply nested... note that the preface
-- introduces two levels of higher order functions, one of
-- which is the normal Lua chunk, which needs to be called with
-- no arguments to produce the second function which needs to
-- be called with the two local functions; this returns yet
-- another function, which is the original Lua chunk.

local function _loadwithpath(pathopen, dir, filename)
  local f = assert(io.open(dir..filename, "r"))
  return assert(loadstring(
    [[return function(pathopen, _loadwithpath) 
        local function loadwithpath(dir, filename)
          return _loadwithpath(pathopen, dir, filename)
        end
        return function()
    ]]
    .. f:read "*a"
    .. "end end", filename)) () (putpath(pathopen, dir), _loadwithpath)
end

-- Finally, the toplevel loadwithpath, which is used to load
-- a chunk from a directory and also to call the above
-- function in order to push the directory onto the path list.

function loadwithpath(dir, filename)
  return _loadwithpath(pathopen, dir, filename)
end

-- Now, we can initialise pathopen to the last resort searches

pathopen = putpath(pathopen, "./") -- Unix style
-- pathopen = putpath(pathopen, ".\\") -- an alternative