[Grace-core] Minutes of Teleconference 23-24.8.12

Bart Jacobs bart.jacobs at cs.kuleuven.be
Sat Aug 25 05:16:43 PDT 2012


Hi Andrew,

On 24/08/2012 19:58, Andrew P. Black wrote:
> I did not understand the interaction of Failboxes with objects.  In particular, what happens if there are inter-object invariants that are manipulated by a failing computation?  Each of the objects, in its own Failbox, may be consistent, but the program as a whole is not.  This sounds like the problem that transactions were designed to solve.

The simplest solution would be to simply associate both objects with the 
same failbox.

More generally: while the failboxes mechanism supports fine-grained 
"units of failure", it was definitely not intended to promote this; 
rather, the intended default is for the entire program to be a single 
unit of failure and for an exception to simply cause the program to 
terminate immediately.

(Note that this is different from the Java's behavior: when a thread's 
"run" method ends with an exception, other threads continue to run. In 
the .NET Framework since version 2.0, the program is terminated, but 
there is still a window between the time the exception is raised and the 
time the exception reaches the toplevel of the thread when finally 
blocks run and abandoned locks can be acquired by other threads.)

The envisaged programming pattern for protecting objects by failboxes is 
for the object's constructor to record a reference to the current 
failbox (rather than a newly created failbox) in a field, and for each 
method to enter this failbox for the duration of its execution. That is, 
an object adopts is creator's failbox. (Syntactic sugar can be 
introduced so that this can be achieved by marking a class as 
"failboxed" or something like that.)

If the objects do need to be separate units of failure, then the 
objects' failboxes can be nested inside a parent failbox. The 
computation that manipulates the objects should run in the parent failbox.

>
>
> On 24 Aug 2012, at 3:05, Bart Jacobs wrote:
>
>> - there should be a mechanism to (asynchronously) run code in another thread. I.e., there should be a method runCode(code) on Thread objects. (This method should probably not be available for general use!)
>>
>>
> Can you explain a bit more why one needs this and when one would use it?  This is different from theBlock.fork, right, in that theBlock runs in a particular existing thread, rather than a new thread.

I assume you mean it the other way around: yes, fork spawns a new 
thread, and t.runCode(theBlock) runs theBlock in existing thread t. This 
is useful for implementing the failboxes mechanism's Fail Fast feature: 
when an exception occurs in a failbox F in one thread, then not only can 
F no longer be entered by other threads, but other threads currently 
running in F get an asynchronous exception, i.e. they get cancelled. 
It's important, however, that when the asynchronous exception arrives at 
a target thread, it is actually raised only if that thread is still 
running inside F. This could be accomplished as follows:

method fail {
     foreach (allThreads) do { t ->
         if (t.currentFailbox == self) then {
             t.runCode {
                 if (t.currentFailbox == self) then { 
FailboxCancellationException.raise }
             }
         }
     }
}

I have implemented failboxes as a Scala library on top of the JVM, but 
cancellation exceptions can leak outside the failbox being cancelled due 
to the lack of a runCode-like mechanism in the Java API. (Note that a 
similar feature, called Asynchronous Procedure Calls, is available in 
the Windows API.)

Bart


Disclaimer: http://www.kuleuven.be/cwis/email_disclaimer.htm


More information about the Grace-core mailing list