lua-users home
lua-l archive

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

>>>>> "Egor" == Egor Skriptunoff <> writes:

 Egor> Hi!

 Egor> I have a problem while trying to use a to-be-closed variable as
 Egor> usual upvalue. An upvalue's lifespan might go beyond the current
 Egor> block, and the lifespan is unknown at compile time.

The approach I've been looking into is to make the equivalent of a C++
auto_ptr, i.e. an object whose sole responsibility is to proxy the
__close of another object.

I have a C implementation, because I also wanted to be able to do some
stuff from C modules with lua_toclose in a reasonably portable (between
5.3 and 5.4) way and almost all the code was the same, but a simple Lua
implementation could be done too (this is largely untested, but uses the
same API as the C version I have):

-- auto_close.lua

local emptytab = {}

local function get_close_method(o)
  if type(o) == 'function' then
    return o
  -- relies on o's metatable not being hidden by __metatable
  -- use debug.getmetatable or the C version if this is an issue
  return (getmetatable(o or emptytab) or emptytab).__close or function()end
local function do_close(o,...)
  local refobj = o.refobj
  o.refobj = nil
  return get_close_method(refobj)(refobj,...)
local function do_get(o)
  return o.refobj
local function do_release(o)
  local refobj = o.refobj
  o.refobj = nil
  return refobj
local meta = {
  __close = do_close,
  __call = do_get,   -- just a convenience shorthand for :get()
  __index = {
    get = do_get,
    release = do_release,
    close = do_close

return function(o,...)
  return setmetatable({ refobj = o }, meta), o, ...


Intended usage:

local auto_close = require 'auto_close'

-- note that this returns both the new close object _and_ all of
-- the original results

local fc <close>, f, err, errno = auto_close(

-- do stuff either with f, or fc() or fc:get()  to access the file

-- then use  fc:release()  to release the underlying file from
-- the auto_close object