/interpreter/tags/at2-build270707/src/edu/vub/at/actors/natives/NATActorMirror.java

http://ambienttalk.googlecode.com/ · Java · 305 lines · 156 code · 32 blank · 117 comment · 4 complexity · 4abef0261e052cb6e60fea042fa92b03 MD5 · raw file

  1. /**
  2. * AmbientTalk/2 Project
  3. * NATActorMirror.java created on Oct 16, 2006 at 1:55:05 PM
  4. * (c) Programming Technology Lab, 2006 - 2007
  5. * Authors: Tom Van Cutsem & Stijn Mostinckx
  6. *
  7. * Permission is hereby granted, free of charge, to any person
  8. * obtaining a copy of this software and associated documentation
  9. * files (the "Software"), to deal in the Software without
  10. * restriction, including without limitation the rights to use,
  11. * copy, modify, merge, publish, distribute, sublicense, and/or
  12. * sell copies of the Software, and to permit persons to whom the
  13. * Software is furnished to do so, subject to the following
  14. * conditions:
  15. *
  16. * The above copyright notice and this permission notice shall be
  17. * included in all copies or substantial portions of the Software.
  18. *
  19. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  20. * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
  21. * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  22. * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
  23. * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
  24. * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  25. * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  26. * OTHER DEALINGS IN THE SOFTWARE.
  27. */
  28. package edu.vub.at.actors.natives;
  29. import edu.vub.at.actors.ATActorMirror;
  30. import edu.vub.at.actors.ATAsyncMessage;
  31. import edu.vub.at.actors.eventloops.BlockingFuture;
  32. import edu.vub.at.actors.natives.DiscoveryManager.Publication;
  33. import edu.vub.at.actors.natives.DiscoveryManager.Subscription;
  34. import edu.vub.at.eval.Evaluator;
  35. import edu.vub.at.exceptions.InterpreterException;
  36. import edu.vub.at.exceptions.XArityMismatch;
  37. import edu.vub.at.exceptions.XIllegalOperation;
  38. import edu.vub.at.exceptions.XTypeMismatch;
  39. import edu.vub.at.objects.ATBoolean;
  40. import edu.vub.at.objects.ATClosure;
  41. import edu.vub.at.objects.ATObject;
  42. import edu.vub.at.objects.ATTypeTag;
  43. import edu.vub.at.objects.ATTable;
  44. import edu.vub.at.objects.coercion.NativeTypeTags;
  45. import edu.vub.at.objects.grammar.ATSymbol;
  46. import edu.vub.at.objects.mirrors.NATIntrospectiveMirror;
  47. import edu.vub.at.objects.mirrors.NativeClosure;
  48. import edu.vub.at.objects.natives.NATByRef;
  49. import edu.vub.at.objects.natives.NATMethod;
  50. import edu.vub.at.objects.natives.OBJNil;
  51. import edu.vub.at.objects.natives.NATNumber;
  52. import edu.vub.at.objects.natives.NATObject;
  53. import edu.vub.at.objects.natives.NATTable;
  54. import edu.vub.at.objects.natives.NATText;
  55. import edu.vub.at.objects.natives.OBJLexicalRoot;
  56. import edu.vub.at.objects.natives.grammar.AGBegin;
  57. import edu.vub.at.objects.natives.grammar.AGSymbol;
  58. /**
  59. * The NATActorMirror class implements the concurrency model of ambienttalk. It continually
  60. * consumes meta-events which are written to a synchronized queue. This way the actor
  61. * is notified of incoming messages, discovered and lost services, etc. When no meta-
  62. * messages are available, the actor consumes base-level messages as they are stored
  63. * in its inbox. These messages have a receiver object internal to the actor and they
  64. * will be invoked on this receiver by the actor's thread.
  65. *
  66. * @author smostinc
  67. */
  68. public class NATActorMirror extends NATByRef implements ATActorMirror {
  69. // INSTANCE VARIABLES
  70. private final ELDiscoveryActor discoveryActor_;
  71. /**
  72. * Creates a new actor on the specified host Virtual Machine. The actor its behaviour
  73. * is intialized by means of the passed parameters and initialization code. The calling
  74. * thread is **blocked** until the actor has been constructed. However, actor behaviour
  75. * and root initialization is carried out by the newly created actor itself.
  76. *
  77. * @param host the VM hosting this actor - after creation, the actor registers itself with this VM
  78. * @param parametersPkt the serialized parameters used to invoke the initialization code
  79. * @param initcodePkt the serialized initialization code used to initialize the actor behaviour
  80. * @param actorMirror this actor's mirror
  81. * @return a far reference to the behaviour of the actor
  82. * @throws InterpreterException
  83. */
  84. public static NATLocalFarRef createActor(ELVirtualMachine host,
  85. Packet parametersPkt,
  86. Packet initcodePkt,
  87. ATActorMirror actorMirror) throws InterpreterException {
  88. BlockingFuture future = new BlockingFuture();
  89. ELActor processor = new ELActor(actorMirror, host);
  90. // notify host VM about my creation
  91. host.actorCreated(processor);
  92. // schedule special 'init' message which will:
  93. // A) create a new behaviour and will unblock creating actor (by passing it a far ref via the future)
  94. // B) unpack the parameters used to invoke the initializatin code
  95. // C) unpack the init code to initialize the behaviour
  96. // D) initialize the root and lobby objects of this actor
  97. processor.event_init(future, parametersPkt, initcodePkt);
  98. try {
  99. return (NATLocalFarRef) future.get();
  100. } catch (Exception e) {
  101. throw (InterpreterException) e;
  102. }
  103. }
  104. /**
  105. * Auxiliary creation method to create an actor with an empty behaviour.
  106. * Equivalent to evaluating:
  107. *
  108. * actor: { nil }
  109. */
  110. public static NATLocalFarRef createEmptyActor(ELVirtualMachine host, ATActorMirror actorMirror) throws InterpreterException {
  111. Packet noParams = new Packet(NATTable.EMPTY);
  112. Packet noinitcode = new Packet(new NATMethod(Evaluator._ANON_MTH_NAM_, NATTable.EMPTY, new AGBegin(NATTable.of(OBJNil._INSTANCE_))));
  113. return createActor(host, noParams, noinitcode, actorMirror);
  114. }
  115. /**
  116. * When initializing a new actor, do not forget that this constructor is still executed by the
  117. * creating actor, not by the created actor. To make the created actor perform something, it is
  118. * necessary to use meta_receive to send itself messages for later execution.
  119. */
  120. public NATActorMirror(ELVirtualMachine host) {
  121. discoveryActor_ = host.discoveryActor_;
  122. }
  123. /* ------------------------------------------
  124. * -- Language Construct to Actor Protocol --
  125. * ------------------------------------------ */
  126. public ATAsyncMessage base_createMessage(ATSymbol selector, ATTable arguments, ATTable types) throws InterpreterException {
  127. return new NATAsyncMessage(OBJNil._INSTANCE_, selector, arguments, types);
  128. }
  129. public ATObject base_createMirror(ATObject reflectee) throws InterpreterException {
  130. return NATIntrospectiveMirror.atValue(reflectee);
  131. }
  132. /**
  133. * A publication object is defined as:
  134. * object: {
  135. * def topic := //topic under which service is published;
  136. * def service := //the exported service object;
  137. * def cancel() { //unexport the service object }
  138. * }
  139. */
  140. public static class NATPublication extends NATObject {
  141. private static final AGSymbol _TOPIC_ = AGSymbol.jAlloc("topic");
  142. private static final AGSymbol _SERVICE_ = AGSymbol.jAlloc("service");
  143. private static final AGSymbol _CANCEL_ = AGSymbol.jAlloc("cancel");
  144. public NATPublication(final ELDiscoveryActor discoveryActor,
  145. ATTypeTag topic, ATObject service,
  146. final Publication pub) throws InterpreterException {
  147. meta_defineField(_TOPIC_, topic);
  148. meta_defineField(_SERVICE_, service);
  149. meta_defineField(_CANCEL_, new NativeClosure(this) {
  150. public ATObject base_apply(ATTable args) throws InterpreterException {
  151. discoveryActor.event_cancelPublication(pub);
  152. return OBJNil._INSTANCE_;
  153. }
  154. });
  155. }
  156. public NATText meta_print() throws InterpreterException {
  157. return NATText.atValue("<publication:"+impl_invokeAccessor(this, _TOPIC_, NATTable.EMPTY)+">");
  158. }
  159. }
  160. /**
  161. * A subscription object is defined as:
  162. * object: {
  163. * def topic := //topic subscribed to;
  164. * def handler := //the closure to be triggered;
  165. * def cancel() { //unsubscribe the handler }
  166. * }
  167. */
  168. public static class NATSubscription extends NATObject {
  169. private static final AGSymbol _TOPIC_ = AGSymbol.jAlloc("topic");
  170. private static final AGSymbol _HANDLER_ = AGSymbol.jAlloc("handler");
  171. private static final AGSymbol _CANCEL_ = AGSymbol.jAlloc("cancel");
  172. public NATSubscription(final ELDiscoveryActor discoveryActor,
  173. ATTypeTag topic, ATClosure handler,
  174. final Subscription sub) throws InterpreterException {
  175. meta_defineField(_TOPIC_, topic);
  176. meta_defineField(_HANDLER_, handler);
  177. meta_defineField(_CANCEL_, new NativeClosure(this) {
  178. public ATObject base_apply(ATTable args) throws InterpreterException {
  179. discoveryActor.event_cancelSubscription(sub);
  180. return OBJNil._INSTANCE_;
  181. }
  182. });
  183. }
  184. public NATText meta_print() throws InterpreterException {
  185. return NATText.atValue("<subscription:"+impl_invokeAccessor(this, _TOPIC_, NATTable.EMPTY)+">");
  186. }
  187. }
  188. public ATObject base_provide(final ATTypeTag topic, final ATObject service) throws InterpreterException {
  189. Publication pub = new Publication(ELActor.currentActor(),
  190. new Packet(topic),
  191. new Packet(service));
  192. discoveryActor_.event_servicePublished(pub);
  193. return new NATPublication(discoveryActor_, topic, service, pub);
  194. }
  195. public ATObject base_require(final ATTypeTag topic, final ATClosure handler, ATBoolean isPermanent) throws InterpreterException {
  196. Subscription sub = new Subscription(ELActor.currentActor(),
  197. new Packet(topic),
  198. new Packet(handler),
  199. isPermanent.asNativeBoolean().javaValue);
  200. discoveryActor_.event_clientSubscribed(sub);
  201. return new NATSubscription(discoveryActor_, topic, handler, sub);
  202. }
  203. /* --------------------------
  204. * -- VM to Actor Protocol --
  205. * -------------------------- */
  206. public ATObject meta_clone() throws InterpreterException {
  207. throw new XIllegalOperation("Cannot clone actor " + toString());
  208. }
  209. /**
  210. * actor.new(closure)
  211. * => same effect as evaluating 'actor: closure'
  212. */
  213. public ATObject meta_newInstance(ATTable initargs) throws InterpreterException {
  214. int length = initargs.base_length().asNativeNumber().javaValue;
  215. if(length != 1)
  216. throw new XArityMismatch("newInstance", 1, length);
  217. ATClosure closure = initargs.base_at(NATNumber.ONE).asClosure();
  218. return OBJLexicalRoot._INSTANCE_.base_actor_(closure);
  219. }
  220. public NATText meta_print() throws InterpreterException {
  221. return NATText.atValue("<actormirror:" + this.hashCode() + ">");
  222. }
  223. /* -----------------------------
  224. * -- Object Passing Protocol --
  225. * ----------------------------- */
  226. /**
  227. * To send a message msg to a receiver object rcv:
  228. * - if rcv is a local reference, schedule accept(msg) in my incoming event queue
  229. * - if rcv is a far reference, schedule msg in far reference's outbox
  230. */
  231. public ATObject meta_send(ATAsyncMessage msg) throws InterpreterException {
  232. ATObject rcv = msg.base_receiver();
  233. if (rcv.isFarReference()) {
  234. return rcv.meta_receive(msg);
  235. } else {
  236. return this.meta_receive(msg);
  237. }
  238. }
  239. public ATObject meta_receive(ATAsyncMessage msg) throws InterpreterException {
  240. ELActor.currentActor().event_acceptSelfSend(msg);
  241. return OBJNil._INSTANCE_;
  242. }
  243. public ATTable meta_typeTags() throws InterpreterException {
  244. return NATTable.of(NativeTypeTags._ACTORMIRROR_);
  245. }
  246. /**
  247. * When default base-level objects send an asynchronous message, they delegate
  248. * this responsibility to their actor by means of this base-level method. The actor's
  249. * base-level 'send' operation dispatches to its meta-level 'send' operation. In effect,
  250. * the semantics of an object sending an async message are the same as those of an actor
  251. * sending an async message directly.
  252. *
  253. * TODO(discuss) is this the desirable semantics for the base-level hook?
  254. */
  255. public ATObject base_send(ATAsyncMessage message) throws InterpreterException {
  256. return meta_send(message);
  257. }
  258. /**
  259. * def install: protocol
  260. * => returns the old installed protocol
  261. *
  262. * @see ATActorMirror#base_install_(ATClosure)
  263. */
  264. public ATObject base_install_(ATActorMirror newActorMirror) throws InterpreterException {
  265. ELActor myEventLoop = ELActor.currentActor();
  266. ATActorMirror oldMirror = myEventLoop.getActorMirror();
  267. myEventLoop.setActorMirror(newActorMirror);
  268. return oldMirror;
  269. }
  270. public ATActorMirror asActorMirror() throws XTypeMismatch {
  271. return this;
  272. }
  273. }