Deterministic Resource Release

Jancy provides a convenient facility for ensuring the deterministic resource release in an inherently non-deterministic GC-world. This is achieved with disposable storage specifier.

Classes in Jancy can have destructors. Therefore, all the necessary resource release operations (e.g. closing files, dropping connections, releasing locks etc) could be placed in destructors. The problem is, destructors in garbage-collected world are not called deterministically. First the Garbage Collector must decide it needs to free unreachable objects; then the mark stage must complete. Only then the destructor of an about-to-be-freed object will be called. Keeping resources acquired for that long is simply not acceptable.

To remedy this problem, Jancy features duck-typed pattern Disposable. All the variables (of class, struct or union types) declared using disposable storage will have their dispose method called upon exiting the scope.

This method will be called no matter which exit route is taken, be it normal control flow, return, break, throw, other exception(s) etc.

Example:

foo ()
{
    // ...

    disposable io.File file;
    file.open ();

    // work with file...
} // <-- file.close () is guaranteed to be called upon exiting the scope

When program runs out of scope where a variable of disposable class was declared in, Jancy compiler will insert a call to dispose method (which is usually aliased to an actual release methods such as close). This method will be called no matter how the program runs out of scope, be it a normal control flow, return, break, continue or an exception.

You can easily write disposable classes yourself. All you have to do is to provide a dispose method (or a dispose alias):

class MyDisposableClass
{
    //...
    dispose ()
    {
        printf ("Releasing resources...");
    }
}

class MyDbConnection
{
    //...
    disconnect ();
    alias dispose = disconnect;
}

foo ()
{
    // ...

    disposable MyDisposableClass c;
    disposable MyDbConnection db;

    // work with c & db...

    throw; // <-- c.dispose () and db.disconnect () will get called
}