001: package dalma;
002:
003: import dalma.spi.ConditionListener;
004:
005: import java.io.Serializable;
006:
007: /**
008: * TODO.
009: *
010: * Derived by endpoint specific implementation to capture endpoint-specific information.
011: * Intances created by a {@link EndPoint} in a endPoint specific way.
012: *
013: * <p>
014: * Condition stays in memory even when the continuation is persisted to a disk,
015: * to wait for the activation event.
016: *
017: * <p>
018: * Condition is serialized as a part of the conversation, allowing conversation
019: * to requeue when the engine is loaded from a file.
020: *
021: * @author Kohsuke Kawaguchi
022: */
023: public abstract class Condition<T> implements Serializable {
024: /**
025: * Receives activation event.
026: */
027: private ConditionListener owner;
028:
029: /**
030: * Activation value from this dock.
031: *
032: * Transient because this field is always null when a conversation is serialized.
033: */
034: private transient T returnValue;
035:
036: /**
037: * Set to true once this {@link Condition} becomes active.
038: */
039: private boolean isActive = false;
040:
041: protected Condition() {
042: }
043:
044: public final ConditionListener getOwner() {
045: return owner;
046: }
047:
048: public final boolean isActive() {
049: return isActive;
050: }
051:
052: public final void park(ConditionListener owner) {
053: this .owner = owner;
054: onParked();
055: }
056:
057: /**
058: * Called after the conversation is parked on this dock.
059: *
060: * {@link #owner}!=null guaranteed. Typically used to queue
061: * this dock.
062: * TODO: should this be the same with onLoad?
063: *
064: * TODO: error handling semantics. what happens if the park fails?
065: */
066: public abstract void onParked();
067:
068: /**
069: * Called when a {@link Conversation} parking on this endPoint is
070: * {@link Conversation#remove() removed}.
071: *
072: * <p>
073: * The implementation is expected to remove this conversation
074: * from any queue it maintains. If the conversation isn't parked,
075: * throw an assertion faillure, as it's a bug in the dalma engine.
076: */
077: public abstract void interrupt();
078:
079: /**
080: * Called after this dock is restored from disk.
081: *
082: * <p>
083: * Typically used to requeue this object.
084: * This happens while the conversation is being restored from the disk.
085: *
086: * <p>
087: * Note that a {@link Condition} may be serialized even after
088: * it gets activated (for example, the conversation may be forced
089: * to persist before a fiber that owns it gets a chance to be executed.)
090: */
091: // TODO: update to work with the new semantics
092: public abstract void onLoad();
093:
094: /**
095: * Resumes the conversation parked on this dock.
096: * Typically invoked by an end point when the conversation should be resumed.
097: *
098: * <p>
099: * Note that the resumed conversation may start executed even before this method
100: * returns.
101: */
102: public final void activate(T retVal) {
103: synchronized (this ) {
104: if (isActive)
105: throw new IllegalStateException(
106: "condition is already active : " + toString());
107: isActive = true;
108: }
109: assert owner != null;
110: synchronized (this ) {
111: this .returnValue = retVal;
112: }
113: // ((ConversationImpl)conv).resume(this);
114: owner.onActivated(this );
115: }
116:
117: public final synchronized T getReturnValue() {
118: assert isActive;
119: return returnValue;
120: }
121:
122: private static final long serialVersionUID = 1L;
123: }
|