[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
- Subject: Re: getfenv question
- From: RLake@...
- Date: Thu, 18 Dec 2003 15:49:03 -0500
> 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