PageRenderTime 49ms CodeModel.GetById 23ms RepoModel.GetById 0ms app.codeStats 0ms

/src/concurrent/java/Future.java

https://bitbucket.org/bedlaczech/fan-1.0
Java | 216 lines | 146 code | 28 blank | 42 comment | 28 complexity | f1855207c6ca89329105a4406c0fb2b3 MD5 | raw file
Possible License(s): CC-BY-SA-3.0
  1. //
  2. // Copyright (c) 2009, Brian Frank and Andy Frank
  3. // Licensed under the Academic Free License version 3.0
  4. //
  5. // History:
  6. // 26 Mar 09 Brian Frank Creation
  7. //
  8. package fan.concurrent;
  9. import fan.sys.*;
  10. import java.util.ArrayList;
  11. /**
  12. * Future is used to manage the entire lifecycle of each
  13. * message send to an Actor. An actor's queue is a linked
  14. * list of messages.
  15. */
  16. public final class Future
  17. extends FanObj
  18. {
  19. //////////////////////////////////////////////////////////////////////////
  20. // Construction
  21. //////////////////////////////////////////////////////////////////////////
  22. Future(Object msg)
  23. {
  24. this.msg = msg;
  25. this.state = PENDING;
  26. }
  27. //////////////////////////////////////////////////////////////////////////
  28. // Obj
  29. //////////////////////////////////////////////////////////////////////////
  30. public Type typeof()
  31. {
  32. if (type == null) type = Type.find("concurrent::Future");
  33. return type;
  34. }
  35. private static Type type;
  36. //////////////////////////////////////////////////////////////////////////
  37. // Future
  38. //////////////////////////////////////////////////////////////////////////
  39. public final boolean isDone()
  40. {
  41. return (state & DONE) != 0;
  42. }
  43. public final boolean isCancelled()
  44. {
  45. return state == DONE_CANCEL;
  46. }
  47. public final Object get() { return get(null); }
  48. public final Object get(Duration timeout)
  49. {
  50. Object r = null;
  51. try
  52. {
  53. synchronized (this)
  54. {
  55. // wait until we enter a done state, the only notifies
  56. // on this object should be from cancel, set, or err
  57. if (timeout == null)
  58. {
  59. // wait forever until done
  60. while ((state & DONE) == 0) wait();
  61. }
  62. else
  63. {
  64. // if not done, then wait with timeout and then
  65. // if still not done throw a timeout exception
  66. if ((state & DONE) == 0)
  67. {
  68. // compute deadline in millis
  69. long deadline = Duration.nowMillis() + timeout.millis();
  70. // loop until we are done or our deadline has passed
  71. while ((state & DONE) == 0)
  72. {
  73. long left = deadline - Duration.nowMillis();
  74. if (left <= 0L) break;
  75. wait(left);
  76. }
  77. // if we still aren't done this is a timeout
  78. if ((state & DONE) == 0) throw TimeoutErr.make("Future.get timed out");
  79. }
  80. }
  81. // if canceled throw CancelErr
  82. if (state == DONE_CANCEL)
  83. throw CancelledErr.make("message canceled");
  84. // if error was raised, raise it to caller
  85. if (state == DONE_ERR)
  86. throw ((Err)result).rebase();
  87. // assign result to local variable for return
  88. r = result;
  89. }
  90. }
  91. catch (InterruptedException e)
  92. {
  93. throw InterruptedErr.make(e);
  94. }
  95. // ensure immutable or safe copy
  96. return Sys.safe(r);
  97. }
  98. public final void cancel()
  99. {
  100. ArrayList wd;
  101. synchronized (this)
  102. {
  103. if ((state & DONE) == 0) state = DONE_CANCEL;
  104. msg = result = null; // allow gc
  105. notifyAll();
  106. wd = whenDone; whenDone = null;
  107. }
  108. sendWhenDone(wd);
  109. }
  110. final void set(Object r)
  111. {
  112. r = Sys.safe(r);
  113. ArrayList wd;
  114. synchronized (this)
  115. {
  116. state = DONE_OK;
  117. result = r;
  118. notifyAll();
  119. wd = whenDone; whenDone = null;
  120. }
  121. sendWhenDone(wd);
  122. }
  123. final void err(Err e)
  124. {
  125. ArrayList wd;
  126. synchronized (this)
  127. {
  128. state = DONE_ERR;
  129. result = e;
  130. notifyAll();
  131. wd = whenDone; whenDone = null;
  132. }
  133. sendWhenDone(wd);
  134. }
  135. //////////////////////////////////////////////////////////////////////////
  136. // When Done
  137. //////////////////////////////////////////////////////////////////////////
  138. final void sendWhenDone(Actor a, Future f)
  139. {
  140. // if already done, then set immediate flag
  141. // otherwise add to our when done list
  142. boolean immediate = false;
  143. synchronized (this)
  144. {
  145. if (isDone()) immediate = true;
  146. else
  147. {
  148. if (whenDone == null) whenDone = new ArrayList();
  149. whenDone.add(new WhenDone(a, f));
  150. }
  151. }
  152. // if immediate we are already done so enqueue immediately
  153. if (immediate)
  154. {
  155. try { a._enqueue(f, false); }
  156. catch (Throwable e) { e.printStackTrace(); }
  157. }
  158. }
  159. static void sendWhenDone(ArrayList list)
  160. {
  161. if (list == null) return;
  162. for (int i=0; i<list.size(); ++i)
  163. {
  164. WhenDone wd = (WhenDone)list.get(i);
  165. try { wd.actor._enqueue(wd.future, false); }
  166. catch (Throwable e) { e.printStackTrace(); }
  167. }
  168. }
  169. static class WhenDone
  170. {
  171. WhenDone(Actor a, Future f) { actor = a; future = f; }
  172. Actor actor;
  173. Future future;
  174. }
  175. //////////////////////////////////////////////////////////////////////////
  176. // Fields
  177. //////////////////////////////////////////////////////////////////////////
  178. static final int PENDING = 0x00;
  179. static final int DONE = 0x0f;
  180. static final int DONE_CANCEL = 0x1f;
  181. static final int DONE_OK = 0x2f;
  182. static final int DONE_ERR = 0x4f;
  183. Object msg; // message send to Actor
  184. Future next; // linked list in Actor
  185. private volatile int state; // processing state of message
  186. private Object result; // result or exception of processing
  187. private ArrayList whenDone; // list of messages to deliver when done
  188. }