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

http://ambienttalk.googlecode.com/ · Java · 344 lines · 158 code · 42 blank · 144 comment · 3 complexity · 56fc08016ea7c261c35855a9554810f6 MD5 · raw file

  1. /**
  2. * AmbientTalk/2 Project
  3. * NATFarReference.java created on Dec 6, 2006 at 9:53:20 AM
  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.ATAsyncMessage;
  30. import edu.vub.at.actors.ATFarReference;
  31. import edu.vub.at.actors.id.ATObjectID;
  32. import edu.vub.at.exceptions.InterpreterException;
  33. import edu.vub.at.exceptions.XIllegalOperation;
  34. import edu.vub.at.exceptions.XSelectorNotFound;
  35. import edu.vub.at.exceptions.XTypeMismatch;
  36. import edu.vub.at.objects.ATBoolean;
  37. import edu.vub.at.objects.ATClosure;
  38. import edu.vub.at.objects.ATField;
  39. import edu.vub.at.objects.ATMethod;
  40. import edu.vub.at.objects.ATNil;
  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.grammar.ATSymbol;
  45. import edu.vub.at.objects.mirrors.NativeClosure;
  46. import edu.vub.at.objects.natives.NATBoolean;
  47. import edu.vub.at.objects.natives.NATByCopy;
  48. import edu.vub.at.objects.natives.NATNil;
  49. import edu.vub.at.objects.natives.NATObject;
  50. import edu.vub.at.objects.natives.NATTable;
  51. import edu.vub.at.objects.natives.NATText;
  52. import edu.vub.at.objects.natives.grammar.AGSymbol;
  53. /**
  54. *
  55. * NATFarReference is the root of the native classes that represent native far references.
  56. * The AmbientTalk/2 implementation distinguishes between two kinds of far references:
  57. * local and remote far references. The former denote far references to objects hosted by
  58. * actors on the same virtual machine. The latter ones denote far references to remote objects
  59. * that are hosted on a separate virtual (and usually even physical) machine.
  60. *
  61. * This abstract superclass encapsulates all of the code that these two kinds of far references
  62. * have in common. The variabilities are delegated to the subclasses. Subclasses should implement
  63. * an abstract method (transmit) which is invoked by this class when the far reference receives
  64. * a message to be forwarded to the remote principal.
  65. *
  66. * Note that far references are pass by copy and resolve to either a near or a new
  67. * actor-local far reference.
  68. *
  69. * Far references encapsulate the same stripes as the remote object they represent.
  70. * As such it becomes possible to perform a stripe test on a far reference as if it
  71. * was performed on the local object itself!
  72. *
  73. * @author tvcutsem
  74. * @author smostinc
  75. */
  76. public abstract class NATFarReference extends NATByCopy implements ATFarReference {
  77. // encodes the identity of the far object pointed at
  78. private final ATObjectID objectId_;
  79. // the stripes with which the remote object is tagged
  80. private final ATStripe[] stripes_;
  81. protected NATFarReference(ATObjectID objectId, ATStripe[] stripes) {
  82. objectId_ = objectId;
  83. stripes_ = stripes;
  84. }
  85. public ATObjectID getObjectId() {
  86. return objectId_;
  87. }
  88. public NATFarReference asNativeFarReference() throws XTypeMismatch {
  89. return this;
  90. }
  91. /**
  92. * After deserialization, ensure that only one unique remote reference exists for
  93. * my target.
  94. */
  95. public ATObject meta_resolve() throws InterpreterException {
  96. // it may be that the once local target object is now remote!
  97. return ELActor.currentActor().resolve(getObjectId(), stripes_);
  98. }
  99. /* ------------------------------
  100. * -- Message Sending Protocol --
  101. * ------------------------------ */
  102. public ATObject meta_receive(ATAsyncMessage message) throws InterpreterException {
  103. return this.transmit(message);
  104. }
  105. protected abstract ATObject transmit(ATAsyncMessage passedMessage) throws InterpreterException;
  106. /**
  107. * @throws XIllegalOperation Cannot synchronously invoke a method on a far reference
  108. */
  109. public ATObject meta_invoke(ATObject receiver, ATSymbol atSelector, ATTable arguments) throws InterpreterException {
  110. throw new XIllegalOperation("Cannot invoke " + atSelector + " on far reference " + this);
  111. }
  112. /**
  113. * @return true if and only if the far object is queried for responses to basic operations such as ==
  114. */
  115. public ATBoolean meta_respondsTo(ATSymbol atSelector) throws InterpreterException {
  116. return super.meta_respondsTo(atSelector);
  117. }
  118. /**
  119. * @throws XSelectorNotFound to ensure proper semantics should the interpreter be
  120. * extended such that it allows extending a far reference in the future.
  121. */
  122. public ATObject meta_doesNotUnderstand(ATSymbol selector) throws InterpreterException {
  123. return super.meta_doesNotUnderstand(selector);
  124. }
  125. /* ------------------------------------
  126. * -- Extension and cloning protocol --
  127. * ------------------------------------ */
  128. /**
  129. * References to objects hosted by another actor are forced to be unique. Therefore
  130. * cloning them throws an XIllegalOperation to avoid inconsistencies by performing
  131. * state updates (through sent messages) after a clone operation.
  132. *
  133. * TODO(discuss) clone: farObject may create a clone on the other actor.
  134. */
  135. public ATObject meta_clone() throws InterpreterException {
  136. throw new XIllegalOperation("Cannot clone far reference " + this);
  137. }
  138. /**
  139. * Cannot create a new instance using a farObject, this should be done either by
  140. * sending rather than invoking new(args) such that the correct method is triggered
  141. * or by invoking newInstance on a farMirror, which will send the call as well.
  142. */
  143. public ATObject meta_newInstance(ATTable initargs) throws InterpreterException {
  144. throw new XIllegalOperation("Cannot create new instance of far reference " + this);
  145. }
  146. /* ------------------------------------------
  147. * -- Slot accessing and mutating protocol --
  148. * ------------------------------------------ */
  149. /**
  150. * @throws XIllegalOperation - cannot select in objects hosted by another actor.
  151. */
  152. public ATObject meta_select(ATObject receiver, ATSymbol selector) throws InterpreterException {
  153. throw new XIllegalOperation("Cannot select " + selector + " from far reference " + this);
  154. }
  155. /**
  156. * @throws XIllegalOperation - cannot lookup in objects hosted by another actor.
  157. */
  158. public ATObject meta_lookup(ATSymbol selector) throws InterpreterException {
  159. throw new XIllegalOperation("Cannot lookup " + selector + " from far reference " + this);
  160. }
  161. /**
  162. * @throws XIllegalOperation - cannot define in objects hosted by another actor.
  163. */
  164. public ATNil meta_defineField(ATSymbol name, ATObject value) throws InterpreterException {
  165. throw new XIllegalOperation("Cannot define field " + name + " in far reference " + this);
  166. }
  167. /**
  168. * @throws XIllegalOperation - cannot assign in objects hosted by another actor.
  169. */
  170. public ATNil meta_assignField(ATObject receiver, ATSymbol name, ATObject value) throws InterpreterException {
  171. throw new XIllegalOperation("Cannot assign field " + name + " in far reference " + this);
  172. }
  173. /**
  174. * @throws XIllegalOperation - cannot assign in objects hosted by another actor.
  175. */
  176. public ATNil meta_assignVariable(ATSymbol name, ATObject value) throws InterpreterException {
  177. throw new XIllegalOperation("Cannot assign variable " + name + " in far reference " + this);
  178. }
  179. /* ----------------------------------------
  180. * -- Object Relation Testing Protocol --
  181. * ---------------------------------------- */
  182. /**
  183. * @return false unless this == original
  184. */
  185. public ATBoolean meta_isCloneOf(ATObject original) throws InterpreterException {
  186. return NATBoolean.atValue(this == original);
  187. }
  188. /**
  189. * @return false unless this == original
  190. */
  191. public ATBoolean meta_isRelatedTo(ATObject object) throws InterpreterException {
  192. return this.meta_isCloneOf(object);
  193. }
  194. /* ---------------------------------
  195. * -- Structural Access Protocol --
  196. * --------------------------------- */
  197. /**
  198. * @throws XIllegalOperation - cannot add fields to an object in another actor.
  199. */
  200. public ATNil meta_addField(ATField field) throws InterpreterException {
  201. return super.meta_addField(field);
  202. }
  203. /**
  204. * @throws XIllegalOperation - cannot add methods to an object in another actor.
  205. */
  206. public ATNil meta_addMethod(ATMethod method) throws InterpreterException {
  207. return super.meta_addMethod(method);
  208. }
  209. /**
  210. * @throws XSelectorNotFound - as the far object has no fields of its own
  211. */
  212. public ATField meta_grabField(ATSymbol fieldName) throws InterpreterException {
  213. return super.meta_grabField(fieldName);
  214. }
  215. /**
  216. * @return a method if and only if the requested selector is a default operator such as ==
  217. * @throws XSelectorNotFound otherwise
  218. */
  219. public ATMethod meta_grabMethod(ATSymbol methodName) throws InterpreterException {
  220. return super.meta_grabMethod(methodName);
  221. }
  222. /**
  223. * @return an empty table
  224. */
  225. public ATTable meta_listFields() throws InterpreterException {
  226. return super.meta_listFields();
  227. }
  228. /**
  229. * @return a table of default methods
  230. */
  231. public ATTable meta_listMethods() throws InterpreterException {
  232. return super.meta_listMethods();
  233. }
  234. /* ----------------------
  235. * -- Output Protocol --
  236. * ---------------------- */
  237. public NATText meta_print() throws InterpreterException {
  238. return NATText.atValue("<far ref:"+objectId_+">");
  239. }
  240. /* --------------------
  241. * -- Mirror Fields --
  242. * -------------------- */
  243. /**
  244. * The stripes of a far reference are the stripes of the remote object
  245. * it points to, plus the FarReference stripe.
  246. */
  247. public ATTable meta_getStripes() throws InterpreterException {
  248. return NATTable.atValue(stripes_);
  249. }
  250. public boolean isFarReference() {
  251. return true;
  252. }
  253. public ATFarReference asFarReference() throws XTypeMismatch {
  254. return this;
  255. }
  256. public static class NATDisconnectionSubscription extends NATObject {
  257. private static final AGSymbol _REFERENCE_ = AGSymbol.jAlloc("reference");
  258. private static final AGSymbol _HANDLER_ = AGSymbol.jAlloc("handler");
  259. private static final AGSymbol _CANCEL_ = AGSymbol.jAlloc("cancel");
  260. public NATDisconnectionSubscription(final NATFarReference reference, ATClosure handler) throws InterpreterException {
  261. this.meta_defineField(_REFERENCE_, reference);
  262. this.meta_defineField(_HANDLER_, handler);
  263. this.meta_defineField(_CANCEL_, new NativeClosure(this) {
  264. public ATObject base_apply(ATTable args) throws InterpreterException {
  265. NATFarReference reference = scope_.meta_select(scope_, _REFERENCE_).asNativeFarReference();
  266. if(reference instanceof NATRemoteFarRef) {
  267. NATRemoteFarRef remote = (NATRemoteFarRef)reference;
  268. ATObject handler = scope_.meta_select(scope_, _HANDLER_);
  269. remote.removeDisconnectionListener(handler);
  270. }
  271. return NATNil._INSTANCE_;
  272. }
  273. });
  274. }
  275. public NATText meta_print() throws InterpreterException {
  276. return NATText.atValue("<disconnection subscription:"+ this.meta_select(this, _REFERENCE_)+">");
  277. }
  278. }
  279. public static class NATReconnectionSubscription extends NATObject {
  280. private static final AGSymbol _REFERENCE_ = AGSymbol.jAlloc("reference");
  281. private static final AGSymbol _HANDLER_ = AGSymbol.jAlloc("handler");
  282. private static final AGSymbol _CANCEL_ = AGSymbol.jAlloc("cancel");
  283. public NATReconnectionSubscription(final NATFarReference reference, ATClosure handler) throws InterpreterException {
  284. this.meta_defineField(_REFERENCE_, reference);
  285. this.meta_defineField(_HANDLER_, handler);
  286. this.meta_defineField(_CANCEL_, new NativeClosure(this) {
  287. public ATObject base_apply(ATTable args) throws InterpreterException {
  288. NATFarReference reference = scope_.meta_select(scope_, _REFERENCE_).asNativeFarReference();
  289. if(reference instanceof NATRemoteFarRef) {
  290. NATRemoteFarRef remote = (NATRemoteFarRef)reference;
  291. ATObject handler = scope_.meta_select(scope_, _HANDLER_);
  292. remote.removeReconnectionListener(handler);
  293. }
  294. return NATNil._INSTANCE_;
  295. }
  296. });
  297. }
  298. public NATText meta_print() throws InterpreterException {
  299. return NATText.atValue("<reconnection subscription:"+ this.meta_select(this, _REFERENCE_)+">");
  300. }
  301. }
  302. }