/interpreter/tags/at_build150307/src/edu/vub/at/actors/natives/NATActorMirror.java

http://ambienttalk.googlecode.com/ · Java · 346 lines · 154 code · 33 blank · 159 comment · 4 complexity · c7cf6f8b30e5ac2ab0638b73c8938384 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.ATStripe;
  43. import edu.vub.at.objects.ATTable;
  44. import edu.vub.at.objects.coercion.NativeStripes;
  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.NATNil;
  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. // schedule special 'init' message which will:
  91. // A) create a new behaviour and will unblock creating actor (by passing it a far ref via the future)
  92. // B) unpack the parameters used to invoke the initializatin code
  93. // C) unpack the init code to initialize the behaviour
  94. // D) initialize the root and lobby objects of this actor
  95. processor.event_init(future, parametersPkt, initcodePkt);
  96. // notify host VM about my creation
  97. host.event_actorCreated(processor);
  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(NATNil._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(ATObject sender, ATSymbol selector, ATTable arguments, ATTable stripes) throws InterpreterException {
  127. return NATAsyncMessage.createAsyncMessage(sender, NATNil._INSTANCE_, selector, arguments, stripes);
  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, ATStripe topic, ATObject service, final Publication pub) throws InterpreterException {
  145. meta_defineField(_TOPIC_, topic);
  146. meta_defineField(_SERVICE_, service);
  147. meta_defineField(_CANCEL_, new NativeClosure(this) {
  148. public ATObject base_apply(ATTable args) throws InterpreterException {
  149. discoveryActor.event_cancelPublication(pub);
  150. return NATNil._INSTANCE_;
  151. }
  152. });
  153. }
  154. public NATText meta_print() throws InterpreterException {
  155. return NATText.atValue("<publication:"+meta_select(this, _TOPIC_)+">");
  156. }
  157. }
  158. /**
  159. * A subscription object is defined as:
  160. * object: {
  161. * def topic := //topic subscribed to;
  162. * def handler := //the closure to be triggered;
  163. * def cancel() { //unsubscribe the handler }
  164. * }
  165. */
  166. public static class NATSubscription extends NATObject {
  167. private static final AGSymbol _TOPIC_ = AGSymbol.jAlloc("topic");
  168. private static final AGSymbol _HANDLER_ = AGSymbol.jAlloc("handler");
  169. private static final AGSymbol _CANCEL_ = AGSymbol.jAlloc("cancel");
  170. public NATSubscription(final ELDiscoveryActor discoveryActor,
  171. ATStripe topic, ATClosure handler,
  172. final Subscription sub) throws InterpreterException {
  173. meta_defineField(_TOPIC_, topic);
  174. meta_defineField(_HANDLER_, handler);
  175. meta_defineField(_CANCEL_, new NativeClosure(this) {
  176. public ATObject base_apply(ATTable args) throws InterpreterException {
  177. discoveryActor.event_cancelSubscription(sub);
  178. return NATNil._INSTANCE_;
  179. }
  180. });
  181. }
  182. public NATText meta_print() throws InterpreterException {
  183. return NATText.atValue("<subscription:"+meta_select(this, _TOPIC_)+">");
  184. }
  185. }
  186. public ATObject base_provide(final ATStripe topic, final ATObject service) throws InterpreterException {
  187. Publication pub = new Publication(ELActor.currentActor(),
  188. new Packet(topic),
  189. new Packet(service));
  190. discoveryActor_.event_servicePublished(pub);
  191. return new NATPublication(discoveryActor_, topic, service, pub);
  192. }
  193. public ATObject base_require(final ATStripe topic, final ATClosure handler, ATBoolean isPermanent) throws InterpreterException {
  194. Subscription sub = new Subscription(ELActor.currentActor(),
  195. new Packet(topic),
  196. new Packet(handler),
  197. isPermanent.asNativeBoolean().javaValue);
  198. discoveryActor_.event_clientSubscribed(sub);
  199. return new NATSubscription(discoveryActor_, topic, handler, sub);
  200. }
  201. /* --------------------------
  202. * -- VM to Actor Protocol --
  203. * -------------------------- */
  204. public ATObject meta_clone() throws InterpreterException {
  205. throw new XIllegalOperation("Cannot clone actor " + toString());
  206. }
  207. /**
  208. * actor.new(closure)
  209. * => same effect as evaluating 'actor: closure'
  210. */
  211. public ATObject meta_newInstance(ATTable initargs) throws InterpreterException {
  212. int length = initargs.base_getLength().asNativeNumber().javaValue;
  213. if(length != 1)
  214. throw new XArityMismatch("newInstance", 1, length);
  215. ATClosure closure = initargs.base_at(NATNumber.ONE).asClosure();
  216. return OBJLexicalRoot._INSTANCE_.base_actor_(closure);
  217. }
  218. public NATText meta_print() throws InterpreterException {
  219. return NATText.atValue("<actormirror:" + this.hashCode() + ">");
  220. }
  221. /* -----------------------------
  222. * -- Object Passing Protocol --
  223. * ----------------------------- */
  224. /**
  225. * To send a message msg to a receiver object rcv:
  226. * - if rcv is a local reference, schedule accept(msg) in my incoming event queue
  227. * - if rcv is a far reference, schedule msg in far reference's outbox
  228. */
  229. public ATObject meta_send(ATAsyncMessage msg) throws InterpreterException {
  230. ATObject rcv = msg.base_getReceiver();
  231. if (rcv.isFarReference()) {
  232. return rcv.meta_receive(msg);
  233. } else {
  234. return this.meta_receive(msg);
  235. }
  236. }
  237. public ATObject meta_receive(ATAsyncMessage msg) throws InterpreterException {
  238. ELActor.currentActor().event_acceptSelfSend(msg);
  239. return NATNil._INSTANCE_;
  240. }
  241. public ATTable meta_getStripes() throws InterpreterException {
  242. return NATTable.of(NativeStripes._ACTORMIRROR_);
  243. }
  244. /**
  245. * When default base-level objects send an asynchronous message, they delegate
  246. * this responsibility to their actor by means of this base-level method. The actor's
  247. * base-level 'send' operation dispatches to its meta-level 'send' operation. In effect,
  248. * the semantics of an object sending an async message are the same as those of an actor
  249. * sending an async message directly.
  250. *
  251. * TODO(discuss) is this the desirable semantics for the base-level hook?
  252. */
  253. public ATObject base_send(ATAsyncMessage message) throws InterpreterException {
  254. return meta_send(message);
  255. }
  256. /**
  257. * def install: protocol
  258. * => returns the old installed protocol
  259. *
  260. * @see ATActorMirror#base_install_(ATClosure)
  261. */
  262. public ATObject base_install_(ATActorMirror newActorMirror) throws InterpreterException {
  263. ELActor myEventLoop = ELActor.currentActor();
  264. ATActorMirror oldMirror = myEventLoop.getActorMirror();
  265. myEventLoop.setActorMirror(newActorMirror);
  266. return oldMirror;
  267. }
  268. /**
  269. * A protocol object is defined as:
  270. * object: {
  271. * def installedMirror := //the installed actor mirror;
  272. * def uninstall() { //uninstall the protocol object }
  273. * }
  274. */
  275. /*public static class NATMOPInstallation extends NATObject {
  276. private static final AGSymbol _INSTALLED_ = AGSymbol.jAlloc("installedMirror");
  277. private static final AGSymbol _UNINSTALL_ = AGSymbol.jAlloc("uninstall");
  278. public NATMOPInstallation(final ELActor eventLoop, ATActorMirror newMirror) throws InterpreterException {
  279. meta_defineField(_INSTALLED_, newMirror);
  280. meta_defineField(_UNINSTALL_, new NativeClosure(this) {
  281. public ATObject base_apply(ATTable args) throws InterpreterException {
  282. ATObject mirrorToRemove = scope_.meta_select(scope_, _INSTALLED_);
  283. ATObject current = eventLoop.getActorMirror();
  284. if (current.equals(mirrorToRemove)) {
  285. // just set the actor mirror to the parent
  286. eventLoop.setActorMirror(mirrorToRemove.meta_getDynamicParent().base_asActorMirror());
  287. } else {
  288. // find the child of the mirror to remove
  289. while ((current != NATNil._INSTANCE_) && !current.meta_getDynamicParent().equals(mirrorToRemove)) {
  290. current = current.meta_getDynamicParent();
  291. }
  292. if (current == NATNil._INSTANCE_) {
  293. // mirror not found
  294. throw new XIllegalOperation("Tried to uninstall a protocol that was not installed: " + mirrorToRemove);
  295. } else {
  296. // current.super := mirrorToRemove.super
  297. current.meta_assignField(current, NATObject._SUPER_NAME_, mirrorToRemove.meta_getDynamicParent());
  298. }
  299. }
  300. return NATNil._INSTANCE_;
  301. }
  302. });
  303. }
  304. public NATText meta_print() throws InterpreterException {
  305. return NATText.atValue("<protocol:"+meta_select(this, _INSTALLED_)+">");
  306. }
  307. }*/
  308. public ATActorMirror asActorMirror() throws XTypeMismatch {
  309. return this;
  310. }
  311. }