lua-users home
lua-l archive

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



I would see some synergy benefits with Lanes and these needs.

With Lanes, pcall() is already used to run particular functions in separate Lua states. This essentially creates a "scope" for such functions.

Using traditional GC mechanism for these scopes is deterministic, since the whole Lua state is cleared at return/error. However, I could survey this a little further and maybe add some ease of use way to add "finalizers" to the lanes. They would be run when the lane has returned or errorred (just before its Lua state is closed).

Considering a case where a project _is_ already using Lanes for its multithreading benefits, is there anything that remains a problem after this? Performance is not downgraded, since pcall() is anyways used.

-asko


David Manura kirjoitti 21.1.2009 kello 7:42:

On Tue, Jan 20, 2009 at 8:48 PM, John Belmonte wrote:
On Tue, Jan 20, 2009 at 5:56 PM, Asko Kauppi wrote:
In other words, what exactly does it _not_ cover, in your and/or David's
opinion?  Give us a list.

Repeated from the previous message for you:

Many applications expose scarce resources to the scripting
environment such as locks; handles for files, memory, and database
transactions; etc.  Such resources need to be released promptly and
deterministically after use, and despite any exceptional condition in
the program.  Of course this can be accomplished with Lua as it is,
but the resulting code is hard to follow [1], highly error prone, and
makes heavy use of protected calls-- limiting potential use of
coroutines.

Decision #1 proposes some more convenient mechanism for deterministic
resource cleanup (a.k.a. "deterministic finalization").  In contrast,
Lua's garbage collector, like most garbage collectors, provides
non-deterministic resource cleanup through finalizers, which in Lua
are the "__gc" metamethods on userdata (accessible in pure Lua code
only through newproxy[8]).  The finalizer of an object typically
closes any resources the object owns, such as to release memory or
close a file handle.  The potential problem is that Lua can delay
running the finalizers as long as it wants to or until you explicitly
call collectgarbage().  In many cases, such as with managed resources
(i.e. memory managed by Lua), this may not be a problem.  In other
cases, as in non-managed resources noted by John above,
non-deterministic resource cleanup can negatively affect program
correctness.  A typical solution to this is for the object to provide
a manually callable dispose method that releases resources.  In the
Lua file object, this is the file:close() method.  This may be fine
except when a block of code contains a number of exit locations via
returns or exceptions.  You may need to take care to call the dispose
method prior to each return and after each exception (i.e. following a
pcall).  In Lua, numerous pcalls and disposals before returns can be
unwieldy.

It's a well recognized problem.  Some .NET descriptions are in [2-5]
for background (.NET is a garbage collected framework that provides a
special mechanism for deterministic finalization).  C# and Python
provide the using and with clauses.  D provides the scope statement.
Java provides a somewhat invasive try/finally.  Traditionally
non-garbage-collected languages may provide other ways of
deterministic cleanup: C++ has RAII and Perl 5 has reference
counting.[1]

Now, personally, in practice, I've only found myself wanting this time
of capability in Lua on a few occasions (but perhaps others with
different applications will have greater need for it):

 - closing file handles upon exceptions
 - closing COM objects on exceptions
 - releasing native OS handles on exceptions, e.g. as once in
    http://lua-users.org/wiki/SerialCommunication
 - and if I used Lua more for database and socket work, quite
possibly that too.

Workarounds I've used are explicit collectgarbage() calls judiciously
placed, adding pcalls (often ugly, affects error tracebacks, and can
conflict with coroutines), and ignoring the problem (sometimes
acceptable).  In the case of file objects, they return on error
(rather than raise like in Java), so pcall can often be avoided unless
intervening code raises errors, but you can still need to explicitly
close on scope exits.

I'll also add that exception safety in Lua may require some practical
assumptions concerning out-of-memory errors[6][7].


[1] http://en.wikipedia.org/wiki/ Resource_Acquisition_Is_Initialization
[2] http://www.deez.info/sengelha/2005/02/11/deterministic-finalization-in-garbage-collected-languages/
[3] http://davidhayden.com/blog/dave/archive/2005/01/13/773.aspx
[4] http://www.codeproject.com/KB/dotnet/idisposable.aspx
[5] http://startbigthinksmall.wordpress.com/2008/04/10/dispose_correctly_with_the_using_statement/
[6] http://lua-users.org/lists/lua-l/2008-10/msg00405.html
[7] http://lua-users.org/lists/lua-l/2008-10/msg00426.html
[8] http://lua-users.org/wiki/HiddenFeatures
[9] http://lua-users.org/wiki/ErrorHandling