lua-users home
lua-l archive

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


Paul:

On Sat, Jun 15, 2019 at 10:37 PM Paul Ducklin <pducklin@outlook.com> wrote:
> I think that the 5.4.0 reference manual ought to:
> * Add __close and __gc into the list of metamethod events so that all valid metamethods are clearly documented in one place.

That I agree with, just yesterday I did a FTS on the 5.3 docs for __gc
and was surprised to hit it just AFTER the metamethods list but not IN
the list. IMO just a mention in the list, even if it is forward link,
would be helpful.



> * Explain the difference between __close and __gc, and clarify that closing a variable doesn’t finalize it.
> (That was not at all clear to me until someone mentioned it here. When you think of “closing” something, the obvious examples are files and sockets, and when you close them you have finished with them and their resources can be reclaimed at once.)

Don't be so sure. In my case, not in Lua but in similar environments,
I have file classes which can be reopened and socket classes which
keep the remote address and byte/packet counts after close, and both
of them are auto-closed on the destructor. And due to this I have
"closer" objects which are similar to <toclose> in purpose ( In C++ I
have "closer x(closeable)" which closes it when going out of scope (
even if closeable is not destroyed ) ). What I mean is you can have
objects which are closed when no longer used but can be partially
useable after close, so you might be interested in open-do whatever
needs it open-close to free SOME resources-do some things which do not
need whole open object - release.

> * Give a simple example of how each might be used. (I know it’s a reference manual not a training book but there are useful examples elsewhere in it and they help a lot.)
> The biggest problem I have with “toclose” is that having come across it in the manual I still have no real idea why it’s there or what I can do with it that I can’t already do with a finalizer.

You can make sure the object is closed as soon as you finish using it.
In the file/socket example, I  would make an idempotent and safe close
method ( safe meaning non error throwing ) and make both __close and
__gc forward to it ( with some extra processing if needed, probably
just aliasing in the file/socket case ).

In a simple script I would just open and operate on files, let the GC
close it when needed.

OTOH if I had a couple thousands coroutines operating on a long lived
server I would try to use <toclose> to avoid hitting "too manyopen
files".

> It’s also not that clear how to use it, given that the manual says that to-be-closed variables are constants. My thought is that seems like a great feature for things like files and sockets as a way of recovering cleanly from errors - but I’ve never thought of files and sockets as “constant variables” because they are all about side effects and continuously changing state.

Bear in mind in lua variables/values are not the same, and a const
variable is more like a C++ reference. In C++ is usual to get files
and similar stuffed in (non const) references ( they are not the same,
as <toclose> can be nil ( documented to be just ignored when exiting
scope ).

> In short: why do I need <toclose>, what do I do with it, and how do I use it properly?

I'm planning to use it for resource management. In your file example,
I can just stash the result of an open() call in a toclose var, making
it return a closeable or nil on error, then test and use it and pass
it around and be sure it will be promptly closed when I exit the
scope, and not some time after that. As an exmpale, in one of my
programs I have an IVR where each call is controlled by a lua state.
When I initialize it, it has to read several files. If I relied on
__gc to close them, they may be open for a long time, as when
initialization finishes it is normal for the IVR to not enter the lua
state until end of call, and this would lead to big OS file handle
usage. Presently I'm careful to pcall() the init code and :close all
of them, having <toclose> will eliminate some tedious to write and
easy to get wrong code.

<toclose> can basically be used to emulate RAII stuff, in languages
which can do it like C++ or the equivalent try/finally which languages
like Java ( in which all objects are dynamic, so no RAII ) use.

Francisco Olarte.