| 
 | ||||||||||
| PREV CLASS NEXT CLASS | FRAMES NO FRAMES | |||||||||
| SUMMARY: NESTED | FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD | |||||||||
java.lang.Objectorg.lightwolf.Flow
public final class Flow
An execution context similar to that of a thread, but with more capabilities.
 Compared to normal threads, flows simplifies the
 implementation of concurrent algorithms and scalable applications. The
 following list summarizes the capabilities of a flow:
 
suspended for later
 resuming, without consuming a Java thread meanwhile.Continuation, fork(int),
 and returnAndContinue().There are some important concepts regarding flows.
 Flow-method: A flow-method is a method marked with the
 FlowMethod annotation. Whenever a flow-method is executing, there
 will be an associated flow instance, which can be obtained by invoking
 current() (such flow is automatically instantiated as described
 below). If a flow-method invokes itself or another flow-method, both methods
 use the same flow instance. If a flow-method invokes a normal (non-flow)
 method, the flow is kept active and can be queried, but some flow utilities
 will disabled until the normal method returns to the invoker flow-method.
 
  Flow-creator: Whenever a flow-method is invoked
 by a normal (non-flow) method, it is called the flow-creator method, because
 it triggers the creation of a new flow (this is done automatically). The flow
 ends when the flow-creator completes normally or by exception. If the
 flow-creator calls itself or another flow-method, no new flow is created, as
 described above.
  
  Flow-controller: The flow-controller is a
 normal (non-flow) method that invokes a flow-method. The flow-controller
 receives signals sent by some flow
 operations, and must handle those signals accordingly. There are standard
 implementations of flow-controllers, such as  
 According to the above specification, when a flow-method A invokes a
 normal method B, and then B invokes a flow-method C, a
 nested flow is created. Regarding the nested flow, B will be the
 flow-controller and C the flow-creator. If C invokes a flow
 utility such as  
 If a flow A belongs to a  
 
execute(Callable) and
 SimpleFlowManager. If it is known that a flow-method will never send
 signals, the flow-controller can be any ordinary method calling a
 flow-method. Many utilities do not send any signal, such as
 split(int) and returnAndContinue().
 fork(int), the effect is applied only to the nested
 flow. The outer flow, on which A is running, is not affected by the
 fork. When the nested flow ends or is suspended, the outer flow becomes
 active again. The number of nesting levels is limited only by memory. Nested
 flows are uncommon because usually flow-methods are designed to call other
 flow-methods, which does not cause the creation of new flow, as mentioned
 above. Nevertheless, nested flows are allowed as an orthogonality feature.
 Process, then every flow B
 derived from A will automatically belong to the same process. Derived
 flows are result of shallow copies. Many utilities
 perform shallow copies, including but not limited to fork(int),
 returnAndContinue() and Continuation.
FlowMethod, 
Process, 
Serialized Form
| Field Summary | |
|---|---|
| static int | ACTIVEA constant indicating that the flow is active. | 
| static int | ENDEDA constant indicating that the flow is ended. | 
| static int | PASSIVEA constant indicating that the flow is passive. | 
| static int | SUSPENDEDA constant indicating that the flow is suspended. | 
| Method Summary | |
|---|---|
|  Future<?> | activate()Equivalent to activate(null). | 
|  Future<?> | activate(Object signalResult)Schedules this flow to resume in another thread. | 
|  Future<?> | activateThrowing(Throwable exception)Schedules this flow to resume in another thread, and throws an exception upon resuming. | 
|  Flow | copy()Performs a shallow copy on this flow. | 
| static Flow | current()Returns the current flow. | 
| static void | end()Ends the current flow. | 
| static void | endFork()Ends the current fork without waiting for any branch. | 
| static Object | execute(Callable<?> callable) | 
| static void | execute(Runnable runnable) | 
| static void | forgetFork()Forgets the current fork without waiting for any branch. | 
| static boolean | forgetProcess()Removes the current flow from its current process. | 
| static int | fork(int n)Starts a fork on the invoker. | 
|  FlowManager | getManager() | 
|  Flow | getPrevious() | 
|  Object | getResult() | 
|  int | getState()This flow's state, which will be ACTIVE,SUSPENDEDorENDED. | 
|  boolean | isActive() | 
|  boolean | isEnded() | 
|  boolean | isSuspended() | 
|  Object | join() | 
| static void | joinProcess(Process process)Adds the current flow to the informed process. | 
| static void | leaveProcess()Removes the current flow from its current process. | 
| static void | log(String msg) | 
| static void | merge()Ends a fork by restoring single-threaded execution. | 
| static boolean | merge(long timeout,
      TimeUnit unit)Attempts to end a fork, or give-up after a timeout elapses. | 
| static Flow | newFlow()Creates and returns a new flow. | 
| static Process | process()The process to which this flow belongs. | 
|  Object | resume()Equivalent to resume(null). | 
|  Object | resume(Object signalResult)Resumes this flow. | 
|  Object | resumeThrowing(Throwable exception)Resumes this flow throwing an exception. | 
| static void | returnAndContinue()Performs returnwhile continuing asynchronously. | 
| static void | returnAndContinue(boolean v)Performs returnboolean-value while continuing
 asynchronously. | 
| static void | returnAndContinue(byte v)Performs returnbyte-value while continuing
 asynchronously. | 
| static void | returnAndContinue(char v)Performs returnchar-value while continuing
 asynchronously. | 
| static void | returnAndContinue(double v)Performs returndouble-value while continuing
 asynchronously. | 
| static void | returnAndContinue(float v)Performs returnfloat-value while continuing
 asynchronously. | 
| static void | returnAndContinue(int v)Causes a method to return an intwhile continuing
 asynchronously. | 
| static void | returnAndContinue(long v)Performs returnlong-value while continuing
 asynchronously. | 
| static void | returnAndContinue(Object v)Performs returnreference-value while continuing
 asynchronously. | 
| static void | returnAndContinue(short v)Performs returnshort-value while continuing
 asynchronously. | 
| static Flow | safeCurrent()Returns the current flow, or throws an exception if there is no current flow. | 
| static Object | signal(FlowSignal signal)Suspends the flow and sends a signal to the flow-controller. | 
| static Flow | snapshot() | 
| static int | split(int n)Initiates concurrent execution on the invoker. | 
|  Flow | streamedCopy() | 
| static Flow | submit(Callable<?> callable) | 
| static Flow | submit(Runnable runnable) | 
| static Object | suspend()Equivalent to suspend(null). | 
| static Object | suspend(Object argument)Suspends the current flow, allowing the current thread to be released. | 
|  Object | waitNotRunning() | 
|  Object | waitSuspended() | 
| Methods inherited from class java.lang.Object | 
|---|
| clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait | 
| Field Detail | 
|---|
public static final int ACTIVE
Thread. When a
 flow method calls a non-flow method, the flow
 will remain active. A flow will move out from active state when the flow-creator returns or when the flow is
 suspended.
getState(), 
Constant Field Valuespublic static final int SUSPENDED
Thread. A
 suspended flow is always stopped at the point of invocation of
 signal(FlowSignal) or higher level methods such as
 suspend(Object) or Continuation.checkpoint(). This means
 it can be resumed with one of the resume()
 methods.
getState(), 
Constant Field Valuespublic static final int PASSIVE
SUSPENDED
 flow.
getState(), 
Constant Field Valuespublic static final int ENDED
end() is called. An ended flow cannot be
 resumed, but it can be passed for the method
 Continuation.placeOnCheckpoint(Flow).
getState(), 
Constant Field Values| Method Detail | 
|---|
public static Flow newFlow()
ENDED
 state, which is suitable to be passed as argument to methods such as
 Continuation.resume(Flow).
ENDED state.public static void execute(Runnable runnable)
public static Object execute(Callable<?> callable)
public static Flow submit(Runnable runnable)
public static Flow submit(Callable<?> callable)
public static Process process()
Process, or null if this flow
         does not belong to any process.joinProcess(Process), 
leaveProcess()public static void joinProcess(Process process)
process - The process to which the current flow will be added. Must
        not be null.
IllegalStateException - If the invoker is not a FlowMethod.
NullPointerException - If the informed process is a
         null reference.Process, 
leaveProcess(), 
forgetProcess()public static void leaveProcess()
null, or
 throws an exception if the current flow does
 not belong to any process.
IllegalStateException - If the invoker is not a FlowMethod,
         or if the current flow does not belong to any process.joinProcess(Process), 
forgetProcess()public static boolean forgetProcess()
null, or
 does nothing if the current flow does not
 belong to any process.
IllegalStateException - If the invoker is not a FlowMethod.joinProcess(Process), 
leaveProcess()public static Flow snapshot()
public static int split(int n)
 This method creates n shallow copies of the
 current flow, then executes each copy concurrently and starting from the
 invocation point. In other words, this method is invoked once, but
 returns 1+n times: 1 time for the invoker, and n times for
 new flows. Notice that split(0) is a no-effect
 operation.
 
 The returned value is an int that identifies the flow to
 which the method returned. It will be 0 for the invoker, and
 a distinct positive integer for new flows, ranging from 1 to
 n.
 
The following example illustrates this behavior:
    void example() {
        System.out.println("Before doFlow()");
        int i = doFlow();
        System.out.printf("doFlow(): %d\n", i);
    }
 
    @FlowMethod
    int doFlow() {
        System.out.println("Before performSplit()");
        int i = performSplit();
        System.out.printf("performSplit(): %d\n", i);
        return i;
    }
 
    @FlowMethod
    int performSplit() {
        System.out.println("Before split(2)");
        int i = Flow.split(2);
        System.out.printf("Split result: %d\n", i);
        return i;
    }
 
 The above snippet prints the following (under fair scheduling
 conditions):
 
 
     Before doFlow()
     Before performSplit()
     Before split(2)
     Split result: 0
     Split result: 1
     Split result: 2
     performSplit(): 0
     performSplit(): 1
     performSplit(): 2
     doFlow(): 0
 
 Each of the created flow runs on a possibly different thread (the actual thread is defined by the flow manager), and will be independent from all other flows, including the invoker. As defined by the shallow copy behavior, all flows share heap objects referenced by the invoker stack frames at the time of invocation.
 If there is an active fork at the time of
 invocation, the invoker will remain on such fork, hence methods such as
 merge() and forgetFork() are still valid for the
 invoker. On the other hand, the newly created flows will be outside any
 fork, which means that invoking merge() and
 forgetFork() before an explicit fork on such flows will cause an
 exception to be thrown.
 
n - The number of flows to create. Must be non-negative.
1 to n for each new
         branch.
IllegalArgumentException - If n is negative.
IllegalStateException - If the invoker is not a FlowMethod.fork(int)public static int fork(int n)
 This method is similar to split(int). In addition to create new
 flows, it makes the invoker and each of the created flows to run in the
 context of a fork. The invoker will stay in the fork until it explicitly
 merges or forgets. As a
 convention in this documentation, new flows created by this method are
 called branches, and the flow that invokes this method is called
 the fork-creator.
 
 If this method is invoked during a previous fork, a nested fork is
 established. This method changes the behavior of merge() and
 other fork-ending methods, which always applies to the innermost fork.
 Because of this, it is recommended to use the structured fork/merge
 style, which use try/finally blocks as in the
 following example:
 
 
    ... // Single-threaded execution.
    int branch = Flow.fork(n);
    try {
        ... // Concurrent execution by n threads.
    } finally {
        Flow.merge();
    }
    ... // Single-threaded execution.
 
 
 The returned value is an int that identifies the branch to
 which the method returned. It will be 0 for the invoker, and
 a distinct positive integer for new branches, ranging from 1
 to n.
 
If parameter n is zero, no new flow will be instantiated and the invoker will continue execution in single-threaded mode. Still, the next fork-ending operation will apply to such fork.
n - The number of branches to create. Must be non-negative.
1 to n for each
         new branch.
IllegalArgumentException - If n is negative.
IllegalStateException - If the invoker is not a FlowMethod.merge(long, TimeUnit), 
forgetFork()
public static void merge()
                  throws InterruptedException
If the invoker is the fork-creator: This method blocks until each of the corresponding branches ends (see below), or until this thread is interrupted, whichever comes first. If the merge is successful (all branches have ended), the invoker exits the fork, restoring the next outer fork, if any. Otherwise (the thread is interrupted while at least one branch is active), the invoker will stay in the fork. If all other branches have ended before invocation of this method, it will return immediately without checking the thread's interrupt flag.
 If the invoker is a branch: This method does not return. It ends
 the flow immediately, as if end() were invoked. Notice that even
 finally blocks will not execute.
 
 This method considers only branches created by the last invocation of
 fork(int).
 
A branch will be active (that is, it will not end) until one of the following happens:
end().merge() or
 merge(long, TimeUnit).forgetFork().endFork().Whenever this method returns normally, it is guaranteed that the invoker was the fork-creator and no branch will be active.
InterruptedException - If the current thread was interrupted while
         there was at least one active branch.
IllegalStateException - If the invoker is not a FlowMethod.fork(int), 
merge(long, TimeUnit), 
forgetFork()
public static boolean merge(long timeout,
                            TimeUnit unit)
                     throws InterruptedException
merge(). Depending on who is
 the invoker, the behavior will be different.
 
 If the invoker is the fork-creator: This method blocks until each
 of the corresponding branches ends (see merge()), or until the
 given timeout expires, or until this thread is interrupted, whichever
 comes first. If the merge is successful (all branches have ended before
 the timeout expire), the invoker exits the fork, restoring the next outer
 fork, if any, and this method returns true. If the timeout
 expires while at least on branch is active, the invoker will stay in the
 fork, and this method returns false. Otherwise (the thread
 is interrupted while at least one branch is active), the invoker will
 stay in the fork. If all other branches have ended before invocation of
 this method, it will return immediately without checking the thread's
 interrupt flag.
 
 If the invoker is a branch: This method does not return. It ends
 the flow immediately, as if end() were invoked. Notice that even
 finally blocks will not execute.
 
Whenever this method returns normally, it is guaranteed that the invoker will be the fork-creator.
true if all other branches have ended,
         false if there was at least one active branch when
         the timeout elapsed.
InterruptedException - If the current thread was interrupted during
         the wait for branches to end.
IllegalStateException - If the invoker is not a FlowMethod.
NullPointerException - If unit is null.fork(int), 
merge(), 
forgetFork()public static void forgetFork()
 If the invoker is the fork-creator, this method exits the fork and
 restores the next outer fork, if any, and then immediately returns. If
 the invoker is a branch, the flow will continue to run on the same
 thread, but "detached" from the fork, as if created by
 split(int). Therefore the fork-creator will consider this branch
 as ended, which means that it might unblock an ongoing call to
 merge() in the fork-creator.
 
 This method does not cause the current flow to end, even if the invoker
 is a branch. If you need this, use endFork() instead.
IllegalStateException - If the invoker is not a FlowMethod.fork(int), 
merge(long, TimeUnit), 
endFork()public static void endFork()
 If the invoker is the fork-creator, this method exits the fork and
 restores the next outer fork, if any, and then immediately returns. If
 the invoker is a branch, it will end the flow immediately, as if
 end() were invoked. This means that it might unblock an ongoing
 call to merge() in the fork-creator.
IllegalStateException - If the invoker is not a FlowMethod.fork(int), 
merge(long, TimeUnit), 
forgetFork()public static void end()
    void example() {
        System.out.println("Before doFlow()");
        int i = doFlow();
        System.out.printf("doFlow(): %d\n", i);
    }
 
    @FlowMethod
    int doFlow() {
        System.out.println("Before end()");
        Flow.end();
        System.out.println("After end()");
        return 5;
    }
 
 
 
 The above snippet prints the following:
 
 
     Before doFlow()
     Before end()
     doFlow(): 0
 
 This method causes the flow-creator to return a "zero" value corresponding to its return type:
null.0.false.(char) 0.
 If the current flow was created by an utility such as split(int)
 or returnAndContinue(), this method never returns and simply
 releases the current thread.
IllegalStateException - If the invoker is not a FlowMethod.public static void returnAndContinue()
return while continuing asynchronously.
 
 This method is used to perform a local split
 operation. In the current flow, it works as if return were
 executed. In a newly created flow, the invoker is resumed from the point
 of invocation. The new flow starts from the invoker method, and not from
 the flow-creator as it would be if
 split(int) were used. The following example illustrates this
 behavior:
 
 
    @FlowMethod
    void example() {
        System.out.println("Before doFlow()");
        doFlow();
        System.out.println("After doFlow()");
        Thread.sleep(50); // Schedule the new flow's thread. 
        System.out.println("Done");
    }
 
    @FlowMethod
    void doFlow() {
        System.out.println("Before returnAndContinue()");
        Flow.returnAndContinue();
        System.out.println("After returnAndContinue()");
    }
 
 
 
 The above example prints the following:
     Before doFlow()
     Before returnAndContinue()
     After doFlow()
     After returnAndContinue()
     Done
 
 
 Notice that the new flow ends when the method doFlow() ends.
 Calling this method more than once in the same method works, but is
 redundant because in the second and subsequent calls, the work doesn't
 need to be done in a new flow.
 
 This method must be called only by a void method. There is
 one version of this method for each possible return value.
IllegalStateException - If the invoker is not a FlowMethod.
IllegalReturnValueException - If the invoker is not a
         void method.public static void returnAndContinue(boolean v)
return boolean-value while continuing
 asynchronously. This method is similar to returnAndContinue(int)
 , except for that it must be invoked for a boolean method.
v - The value to return.
IllegalStateException - If the invoker is not a FlowMethod.
IllegalReturnValueException - If the invoker is not a
         boolean method.public static void returnAndContinue(char v)
return char-value while continuing
 asynchronously. This method is similar to returnAndContinue(int)
 , except for that it must be invoked for a char method.
v - The value to return.
IllegalStateException - If the invoker is not a FlowMethod.
IllegalReturnValueException - If the invoker is not a
         char method.public static void returnAndContinue(byte v)
return byte-value while continuing
 asynchronously. This method is similar to returnAndContinue(int)
 , except for that it must be invoked for a byte method.
v - The value to return.
IllegalStateException - If the invoker is not a FlowMethod.
IllegalReturnValueException - If the invoker is not a
         byte method.public static void returnAndContinue(short v)
return short-value while continuing
 asynchronously. This method is similar to returnAndContinue(int)
 , except for that it must be invoked for a short method.
v - The value to return.
IllegalStateException - If the invoker is not a FlowMethod.
IllegalReturnValueException - If the invoker is not a
         short method.public static void returnAndContinue(int v)
int while continuing
 asynchronously.
 
 This method is used to perform a local split
 operation. In the current flow, it works as if return v were
 executed. In a newly created flow, the invoker is resumed from the point
 of invocation. The new flow starts from the invoker method, and not from
 the flow-creator as it would be if
 split(int) were used. The following example illustrates this
 behavior:
 
    @FlowMethod
    void example() {
        System.out.println("Before doFlow()");
        int i = doFlow();
        System.out.printf("doFlow(): %d\n", i);
        Thread.sleep(50); // Schedule the new flow's thread. 
        System.out.println("Done");
    }
 
    @FlowMethod
    int doFlow() {
        System.out.println("Before returnAndContinue()");
        Flow.returnAndContinue(123);
        System.out.println("After returnAndContinue()");
        return 456;
    }
 
 The above example prints the following:
 
 
     Before doFlow()
     Before returnAndContinue()
     doFlow(): 123
     After returnAndContinue()
     Done
 
 
 Notice that the new flow ends when the method doFlow() ends.
 Hence the value of the actual return statement (
 456 in the example) is discarded. Calling this method more
 than once in the same method works, but is redundant because in the
 second and subsequent calls, the work doesn't need to be done in a new
 flow.
 
 This method must be called only by an int method. There is
 one version of this method for each possible return value.
v - The value to return.
IllegalStateException - If the invoker is not a FlowMethod.
IllegalReturnValueException - If the invoker is not an
         int method.public static void returnAndContinue(long v)
return long-value while continuing
 asynchronously. This method is similar to returnAndContinue(int)
 , except for that it must be invoked for a long method.
v - The value to return.
IllegalStateException - If the invoker is not a FlowMethod.
IllegalReturnValueException - If the invoker is not a
         long method.public static void returnAndContinue(float v)
return float-value while continuing
 asynchronously. This method is similar to returnAndContinue(int)
 , except for that it must be invoked for a float method.
v - The value to return.
IllegalStateException - If the invoker is not a FlowMethod.
IllegalReturnValueException - If the invoker is not a
         float method.public static void returnAndContinue(double v)
return double-value while continuing
 asynchronously. This method is similar to returnAndContinue(int)
 , except for that it must be invoked for a double method.
v - The value to return.
IllegalStateException - If the invoker is not a FlowMethod.
IllegalReturnValueException - If the invoker is not a
         double method.public static void returnAndContinue(Object v)
return reference-value while continuing
 asynchronously. This method is similar to returnAndContinue(int)
 , except for that it must be invoked for an reference method.
 
v - The value to return.
IllegalStateException - If the invoker is not a FlowMethod.
IllegalReturnValueException - If the invoker is not a reference
         method.
ClassCastException - If the returned object is not assignable to
         the invoker's return type.public static Object suspend()
suspend(null).
public static Object suspend(Object argument)
SuspendSignal to the flow-controller, which by
 default does
 nothing. This can be used to
 release the current thread to other tasks.
 
 The informed argument is simply passed to the
 constructor of
 SuspendSignal, and can be later obtained, usually in the flow-controller, by invoking
 SuspendSignal.getResult(). The informed argument is usually used
 to tell the reason of suspension. That is, its usually a merely
 informative value, used for debugging and tracing purposes.
 
 When a flow chooses to suspend itself, it usually must provide means to
 be resumed when some event occurs, and not
 rely on the flow-controller for this task. For example, if a flow chooses
 to suspend itself while waiting for user input, it should store
 itself on the user's session storage
 before suspending, so that when user input happens, the event
 handler can invoke resume(Object) on the suspended flow.
 
 This method returns the value passed to resume(Object), and
 might throw an exception if resumeThrowing(Throwable) were
 instead used. This method can return multiple times and/or in different
 flows, at the discretion of whoever uses the suspended flow.
 
 This method behaves exactly as the expression
 signal(new SuspendSignal(argument)).
argument - The argument to be associated with SuspendSignal.
resume(Object).signal(FlowSignal), 
suspend(), 
SuspendSignal, 
resume(), 
resume(Object)public static Object signal(FlowSignal signal)
This method first suspends the current flow at the point of invocation. Then it sends the specified signal to the flow-controller, as if the signal were thrown by the flow-creator (see below). After this, the next actions are fully determined by the flow-controller, which typically uses the signal to decide.
 This method returns only when the flow-controller invokes a
 resume method (see below) on this flow or on a copy. Notice
 that this method may complete on a different flow and it may also
 complete more than once, at the discretion of the flow-controller.
 
Although the signal is an exception, this method doesn't throw the signal on the current flow. The signal is thrown by the subsystem after the flow have been suspended. To the flow-controller, the signal appears to have been thrown by the flow-creator. This mechanism is illustrated in the following snippet:
    void example() { // This is the flow-controller.
        try {
            doFlow();
            System.out.println("doFlow() returned");
        } catch (FlowSignal signal) {
            System.out.println("Caught by the flow-controller");
            System.out.println("Calling Flow.resume()");
            signal.getFlow().resume();
            System.out.println("Flow ended");
        }
    }
 
    @FlowMethod
    void doFlow() { // This is the flow-creator.
        try {
            doSignal();
            System.out.println("doSignal() returned");
        } catch (FlowSignal signal) {
            System.out.println("Caught by the flow-creator");
        }
    }
 
    @FlowMethod
    void doSignal() { // This is an ordinary flow method.
        try {
            System.out.println("Sending signal");
            FlowSignal signal = new MyFlowSignal();
            Flow.signal(signal);
            System.out.println("Returned from signal (resumed)");
        } catch (FlowSignal signal) {
            System.out.println("Caught by doSignal()");
        }
    }
 
 
 
 The above snippet prints the following:
 
 
     Sending signal
     Caught by the flow-controller
     Calling Flow.resume()
     Returned from signal (resumed)
     doSignal() returned
     Flow ended
 
 The flow-controller can, among other actions, create a
 shallow copy of this flow, serialize this flow and
 deserialize in another machine instance, ignore the signal and never
 resume, or wait for some specific condition before
 resuming. To provide satisfactory usability, the flow-controller must
 proceed as specified by the received signal
 object. There are some well-known signal classes such as
 DelayedCallSignal and SuspendSignal, but developers are
 free to create new signals, as long as they provide support for them in
 the flow-controller.
 
 The completion of this method depends on the chosen resume
 method:
 
resume(), this method returns
 null.resume(Object), this method
 returns the object passed to the resume method.resumeThrowing(Throwable), this
 method throws ResumeException whose
 cause is the exception passed to the
 resumeThrowing method.
 This method is used to implement utilities such as
 suspend(Object) and ThreadFreeLock. It is the lowest
 level API for implementing features such as releasing a pooled thread
 before completion and serializing thread state for long running
 processes.
signal - The signal to be sent to the flow-controller.
resume(Object) method.
IllegalStateException - If the invoker is not a FlowMethod.
NullPointerException - If signal is null.
ResumeException - If the flow is resuming through
         resumeThrowing(Throwable).public static Flow current()
null. The current flow will always be
 ACTIVE .
null no flow method is running on the current thread.public static Flow safeCurrent()
current(), except in that it never
 returns null. In the absence of a current flow, it will
 throw an exception.
IllegalStateException - If there is no current flow.public static void log(String msg)
public FlowManager getManager()
public Flow getPrevious()
public int getState()
ACTIVE, SUSPENDED or
 ENDED.
waitSuspended(), 
waitNotRunning()public boolean isActive()
public boolean isSuspended()
public boolean isEnded()
public Object resume()
resume(null).
public Object resumeThrowing(Throwable exception)
signal(FlowSignal) inside this flow to throw a
 ResumeException whose cause is
 the informed exception.
 
 In all other aspects, this method behaves as resume(Object).
 That is, the invoker will block until the flow completes, will be the new
 flow-controller, and might need to handle
 signals.
exception - The exception that will be the cause of the
        ResumeException to be throwed.
null if the
         flow-creator is a void method.
NullPointerException - If exception is null.
IllegalStateException - If this flow is not suspended.signal(FlowSignal), 
resume(Object), 
activateThrowing(Throwable)public Object resume(Object signalResult)
signal(FlowSignal) inside this flow to return. The flow resumes
 execution directly on the current thread, and therefore this method only
 returns when the flow finishes. This means that the invoker of this
 method will be the new flow-controller, and
 might need to handle signals. To resume
 this flow on another thread, use activate(Object).
 
 The informed parameter is simply returned to the flow as a normal result
 of signal(FlowSignal).
 
The completion of this method is defined as follows:
FlowException having the exception as its
 cause.
 resume(Object) will behave as an
 ordinary flow-controller.
signalResult - The value that signal(FlowSignal) must
        return to its invoker.
null if the
         flow-creator is a void method.
IllegalStateException - If this flow is not suspended.signal(FlowSignal), 
resume(), 
resumeThrowing(Throwable), 
activate(), 
activate(Object)public Future<?> activate()
activate(null).
public Future<?> activateThrowing(Throwable exception)
activate(Object), except in that resuming is done with
 resumeThrowing(Throwable) instead of resume(Object).
resumeThrowing(Throwable), 
activate(), 
activate(Object)public Future<?> activate(Object signalResult)
FlowManager.submit(Flow, Object) method, which will assign resume
 execution to some thread. The thread's run is a simple flow-controller. It can be roughly defined by
 this pseudo-code:
 
 
     public void run() {
         try {
             flow.resume(signalResult);
         } catch (FlowSignal signal) {
             signal.defaultAction(); // Always call the default action.
         } catch (Throwable e) {
             log(e); // Logs the exception.
         }
     }
 
 
 The returned Future can be use to query execution status. Notice
 that if such Future is done, it
 does not necessarily means that the flow finished.
 Future.isDone() will return true even when the flow
 was just suspended.
signalResult - The argument to be passed to resume(Object)
        method. This argument will be returned to the flow by the
        signal(FlowSignal) that causes suspension.
Future that can be used to query execution status.resume(Object), 
activate(), 
activateThrowing(Throwable)public Flow copy()
 If this flow is suspended, the returned copy can be
 resumed and it will run just after the suspend
 invocation, as if it were suspended by itself. This process does not
 affect the current flow, which was only the source in a copy operation.
 Many copies can be created from a single flow, which allows
 implementation of utilities such as split(int) and
 EventPicker.
 
 The target flow must be either suspended or ended, and hence this method
 cannot be used to copy a running flow. To get the state of a running
 flow, use Continuation.
 
IllegalStateException - If this flow is not suspended nor ended.public Flow streamedCopy()
public Object join()
            throws InterruptedException
InterruptedException
public Object waitSuspended()
                     throws InterruptedException
InterruptedException
public Object waitNotRunning()
                      throws InterruptedException
InterruptedExceptionpublic Object getResult()
| 
 | ||||||||||
| PREV CLASS NEXT CLASS | FRAMES NO FRAMES | |||||||||
| SUMMARY: NESTED | FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD | |||||||||