roxen.lists.pike.general

Subject Author Date
Re: MutexKeys, garbage collectors, destructors and optimisers Martin Stjernholm <mast[at]lysator[dot]liu[dot]se> 03-02-2009
"Stephen R. van den Berg" <<srb[at]cuci.nl>> wrote:

> I've said this before, but it yet again shows that it would be rather
> desirable to get semantics on the moment destructors are called which
> coincide with when C++ calls them (at the logical end of a block).
> It's quite unfortunate that you need to know how the optimiser works to
> ensure that certain side-effects in destructors are performed not too
> soon or too late.

Considering how bug prone, but more importantly thoroughly disruptive
that semantic (i.e. that things are destructed immediately when
reaching zero refs) is to gc optimizations, I'd say we should rather
try to go away from it and replace it with explicit language
constructs where these things matter.

In this case the recipe could be something like this:

  Sql.Sql sql_cache_get(...)
  {
    destruct_on_exit (Thread.MutexKey key = roxenloader.sq_cache_lock()) {
      Sql.Sql res = roxenloader.sq_cache_get(db, sessiondbs, charset);
      if (res) return res;
      // Release the lock during the call to get_sql_handler(),
      // since it may take quite a bit of time...
      destruct(key);
      if (res = get_sql_handler(url)) {
        // Now we need the lock again...
        key = roxenloader.sq_cache_lock();
        res = roxenloader.sq_cache_set(db, res, sessiondbs, charset);
      }
    }
  }

Here the "destruct_on_exit" block informs the compiler that the
contents of the variable "key" must be destructed when execution
leaves the block. It would do that regardless of the amount of refs to
the MutexKey object. (The name "destruct_on_exit" would preferably be
cireplaced with something more succinct.)

Explicit constructs both makes the code more clear on what the
programmer intends, and allows the compiler to optimize better, e.g.
do more aggressive tail recursion when there is no "destruct_on_exit"
block.