I’m working on a scriptable object model that includes completion objects for asynchronous computation, such that end-user scripts can wait upon logical combinations of the completion objects. The problem is that if I use the builtin monitor objects via wait() and notify()/notifyAll() then there’s no mechanism for waiting for multiple objects; if I use CountDownLatch it’s unclear how to compose more than one object.
I want something like this:
/** object representing the state of completion of an operation
* which is initially false, then becomes true when the operation completes */
interface Completion
{
/** returns whether the operation is complete */
public boolean isDone();
/** waits until the operation is complete */
public void await() throws InterruptedException;
}
class SomeObject
{
public Completion startLengthyOperation() { ... }
}
class Completions
{
public Completion or(Completion ...objects);
public Completion and(Completion ...objects);
}
so that a script or end-application can do this:
SomeObject obj1, obj2, obj3;
... /* assign obj1,2,3 */
Completion c1 = obj1.startLengthOperation();
Completion c2 = obj2.startLengthOperation();
Completion c3 = obj3.startLengthOperation();
Completion anyOf = Completions.or(c1,c2,c3);
Completion allOf = Completions.and(c1,c2,c3);
anyOf.await(); // wait for any of the 3 to be finished
... // do something
allOf.await(); // wait for all of the 3 to be finished
... // do something else
The and() case is easy to handle if I implement using CountDownLatch — I just wait for all of them in any sequence. But how can I handle the or() case?
Sounds like Guava’s
ListenableFuture, or at least like you should adapt some of the ideas. The key point is to be able to add listeners for the completion of a thing. At that point, the implementation is fairly straightforward: you just create aCompletionobject and add listeners to each of the targetCompletions to mark theorCompletionas complete.