/interpreter/tags/at2-build270707/src/edu/vub/at/actors/natives/NATActorMirror.java
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 */ 28package edu.vub.at.actors.natives; 29 30import edu.vub.at.actors.ATActorMirror; 31import edu.vub.at.actors.ATAsyncMessage; 32import edu.vub.at.actors.eventloops.BlockingFuture; 33import edu.vub.at.actors.natives.DiscoveryManager.Publication; 34import edu.vub.at.actors.natives.DiscoveryManager.Subscription; 35import edu.vub.at.eval.Evaluator; 36import edu.vub.at.exceptions.InterpreterException; 37import edu.vub.at.exceptions.XArityMismatch; 38import edu.vub.at.exceptions.XIllegalOperation; 39import edu.vub.at.exceptions.XTypeMismatch; 40import edu.vub.at.objects.ATBoolean; 41import edu.vub.at.objects.ATClosure; 42import edu.vub.at.objects.ATObject; 43import edu.vub.at.objects.ATTypeTag; 44import edu.vub.at.objects.ATTable; 45import edu.vub.at.objects.coercion.NativeTypeTags; 46import edu.vub.at.objects.grammar.ATSymbol; 47import edu.vub.at.objects.mirrors.NATIntrospectiveMirror; 48import edu.vub.at.objects.mirrors.NativeClosure; 49import edu.vub.at.objects.natives.NATByRef; 50import edu.vub.at.objects.natives.NATMethod; 51import edu.vub.at.objects.natives.OBJNil; 52import edu.vub.at.objects.natives.NATNumber; 53import edu.vub.at.objects.natives.NATObject; 54import edu.vub.at.objects.natives.NATTable; 55import edu.vub.at.objects.natives.NATText; 56import edu.vub.at.objects.natives.OBJLexicalRoot; 57import edu.vub.at.objects.natives.grammar.AGBegin; 58import edu.vub.at.objects.natives.grammar.AGSymbol; 59 60/** 61 * The NATActorMirror class implements the concurrency model of ambienttalk. It continually 62 * consumes meta-events which are written to a synchronized queue. This way the actor 63 * is notified of incoming messages, discovered and lost services, etc. When no meta- 64 * messages are available, the actor consumes base-level messages as they are stored 65 * in its inbox. These messages have a receiver object internal to the actor and they 66 * will be invoked on this receiver by the actor's thread. 67 * 68 * @author smostinc 69 */ 70public class NATActorMirror extends NATByRef implements ATActorMirror { 71 72 // INSTANCE VARIABLES 73 74 private final ELDiscoveryActor discoveryActor_; 75 76 /** 77 * Creates a new actor on the specified host Virtual Machine. The actor its behaviour 78 * is intialized by means of the passed parameters and initialization code. The calling 79 * thread is **blocked** until the actor has been constructed. However, actor behaviour 80 * and root initialization is carried out by the newly created actor itself. 81 * 82 * @param host the VM hosting this actor - after creation, the actor registers itself with this VM 83 * @param parametersPkt the serialized parameters used to invoke the initialization code 84 * @param initcodePkt the serialized initialization code used to initialize the actor behaviour 85 * @param actorMirror this actor's mirror 86 * @return a far reference to the behaviour of the actor 87 * @throws InterpreterException 88 */ 89 public static NATLocalFarRef createActor(ELVirtualMachine host, 90 Packet parametersPkt, 91 Packet initcodePkt, 92 ATActorMirror actorMirror) throws InterpreterException { 93 94 BlockingFuture future = new BlockingFuture(); 95 ELActor processor = new ELActor(actorMirror, host); 96 97 // notify host VM about my creation 98 host.actorCreated(processor); 99 100 // schedule special 'init' message which will: 101 // A) create a new behaviour and will unblock creating actor (by passing it a far ref via the future) 102 // B) unpack the parameters used to invoke the initializatin code 103 // C) unpack the init code to initialize the behaviour 104 // D) initialize the root and lobby objects of this actor 105 processor.event_init(future, parametersPkt, initcodePkt); 106 107 try { 108 return (NATLocalFarRef) future.get(); 109 } catch (Exception e) { 110 throw (InterpreterException) e; 111 } 112 } 113 114 /** 115 * Auxiliary creation method to create an actor with an empty behaviour. 116 * Equivalent to evaluating: 117 * 118 * actor: { nil } 119 */ 120 public static NATLocalFarRef createEmptyActor(ELVirtualMachine host, ATActorMirror actorMirror) throws InterpreterException { 121 Packet noParams = new Packet(NATTable.EMPTY); 122 Packet noinitcode = new Packet(new NATMethod(Evaluator._ANON_MTH_NAM_, NATTable.EMPTY, new AGBegin(NATTable.of(OBJNil._INSTANCE_)))); 123 return createActor(host, noParams, noinitcode, actorMirror); 124 } 125 126 127 /** 128 * When initializing a new actor, do not forget that this constructor is still executed by the 129 * creating actor, not by the created actor. To make the created actor perform something, it is 130 * necessary to use meta_receive to send itself messages for later execution. 131 */ 132 public NATActorMirror(ELVirtualMachine host) { 133 discoveryActor_ = host.discoveryActor_; 134 } 135 136 /* ------------------------------------------ 137 * -- Language Construct to Actor Protocol -- 138 * ------------------------------------------ */ 139 140 public ATAsyncMessage base_createMessage(ATSymbol selector, ATTable arguments, ATTable types) throws InterpreterException { 141 return new NATAsyncMessage(OBJNil._INSTANCE_, selector, arguments, types); 142 } 143 144 public ATObject base_createMirror(ATObject reflectee) throws InterpreterException { 145 return NATIntrospectiveMirror.atValue(reflectee); 146 } 147 148 /** 149 * A publication object is defined as: 150 * object: { 151 * def topic := //topic under which service is published; 152 * def service := //the exported service object; 153 * def cancel() { //unexport the service object } 154 * } 155 */ 156 public static class NATPublication extends NATObject { 157 private static final AGSymbol _TOPIC_ = AGSymbol.jAlloc("topic"); 158 private static final AGSymbol _SERVICE_ = AGSymbol.jAlloc("service"); 159 private static final AGSymbol _CANCEL_ = AGSymbol.jAlloc("cancel"); 160 public NATPublication(final ELDiscoveryActor discoveryActor, 161 ATTypeTag topic, ATObject service, 162 final Publication pub) throws InterpreterException { 163 meta_defineField(_TOPIC_, topic); 164 meta_defineField(_SERVICE_, service); 165 meta_defineField(_CANCEL_, new NativeClosure(this) { 166 public ATObject base_apply(ATTable args) throws InterpreterException { 167 discoveryActor.event_cancelPublication(pub); 168 return OBJNil._INSTANCE_; 169 } 170 }); 171 } 172 public NATText meta_print() throws InterpreterException { 173 return NATText.atValue("<publication:"+impl_invokeAccessor(this, _TOPIC_, NATTable.EMPTY)+">"); 174 } 175 } 176 177 /** 178 * A subscription object is defined as: 179 * object: { 180 * def topic := //topic subscribed to; 181 * def handler := //the closure to be triggered; 182 * def cancel() { //unsubscribe the handler } 183 * } 184 */ 185 public static class NATSubscription extends NATObject { 186 private static final AGSymbol _TOPIC_ = AGSymbol.jAlloc("topic"); 187 private static final AGSymbol _HANDLER_ = AGSymbol.jAlloc("handler"); 188 private static final AGSymbol _CANCEL_ = AGSymbol.jAlloc("cancel"); 189 public NATSubscription(final ELDiscoveryActor discoveryActor, 190 ATTypeTag topic, ATClosure handler, 191 final Subscription sub) throws InterpreterException { 192 meta_defineField(_TOPIC_, topic); 193 meta_defineField(_HANDLER_, handler); 194 meta_defineField(_CANCEL_, new NativeClosure(this) { 195 public ATObject base_apply(ATTable args) throws InterpreterException { 196 discoveryActor.event_cancelSubscription(sub); 197 return OBJNil._INSTANCE_; 198 } 199 }); 200 } 201 public NATText meta_print() throws InterpreterException { 202 return NATText.atValue("<subscription:"+impl_invokeAccessor(this, _TOPIC_, NATTable.EMPTY)+">"); 203 } 204 } 205 206 public ATObject base_provide(final ATTypeTag topic, final ATObject service) throws InterpreterException { 207 Publication pub = new Publication(ELActor.currentActor(), 208 new Packet(topic), 209 new Packet(service)); 210 discoveryActor_.event_servicePublished(pub); 211 return new NATPublication(discoveryActor_, topic, service, pub); 212 } 213 214 public ATObject base_require(final ATTypeTag topic, final ATClosure handler, ATBoolean isPermanent) throws InterpreterException { 215 Subscription sub = new Subscription(ELActor.currentActor(), 216 new Packet(topic), 217 new Packet(handler), 218 isPermanent.asNativeBoolean().javaValue); 219 discoveryActor_.event_clientSubscribed(sub); 220 return new NATSubscription(discoveryActor_, topic, handler, sub); 221 } 222 223 /* -------------------------- 224 * -- VM to Actor Protocol -- 225 * -------------------------- */ 226 227 public ATObject meta_clone() throws InterpreterException { 228 throw new XIllegalOperation("Cannot clone actor " + toString()); 229 } 230 231 /** 232 * actor.new(closure) 233 * => same effect as evaluating 'actor: closure' 234 */ 235 public ATObject meta_newInstance(ATTable initargs) throws InterpreterException { 236 int length = initargs.base_length().asNativeNumber().javaValue; 237 if(length != 1) 238 throw new XArityMismatch("newInstance", 1, length); 239 240 ATClosure closure = initargs.base_at(NATNumber.ONE).asClosure(); 241 return OBJLexicalRoot._INSTANCE_.base_actor_(closure); 242 } 243 244 public NATText meta_print() throws InterpreterException { 245 return NATText.atValue("<actormirror:" + this.hashCode() + ">"); 246 } 247 248 /* ----------------------------- 249 * -- Object Passing Protocol -- 250 * ----------------------------- */ 251 252 /** 253 * To send a message msg to a receiver object rcv: 254 * - if rcv is a local reference, schedule accept(msg) in my incoming event queue 255 * - if rcv is a far reference, schedule msg in far reference's outbox 256 */ 257 public ATObject meta_send(ATAsyncMessage msg) throws InterpreterException { 258 ATObject rcv = msg.base_receiver(); 259 if (rcv.isFarReference()) { 260 return rcv.meta_receive(msg); 261 } else { 262 return this.meta_receive(msg); 263 } 264 } 265 266 public ATObject meta_receive(ATAsyncMessage msg) throws InterpreterException { 267 ELActor.currentActor().event_acceptSelfSend(msg); 268 return OBJNil._INSTANCE_; 269 } 270 271 public ATTable meta_typeTags() throws InterpreterException { 272 return NATTable.of(NativeTypeTags._ACTORMIRROR_); 273 } 274 275 /** 276 * When default base-level objects send an asynchronous message, they delegate 277 * this responsibility to their actor by means of this base-level method. The actor's 278 * base-level 'send' operation dispatches to its meta-level 'send' operation. In effect, 279 * the semantics of an object sending an async message are the same as those of an actor 280 * sending an async message directly. 281 * 282 * TODO(discuss) is this the desirable semantics for the base-level hook? 283 */ 284 public ATObject base_send(ATAsyncMessage message) throws InterpreterException { 285 return meta_send(message); 286 } 287 288 /** 289 * def install: protocol 290 * => returns the old installed protocol 291 * 292 * @see ATActorMirror#base_install_(ATClosure) 293 */ 294 public ATObject base_install_(ATActorMirror newActorMirror) throws InterpreterException { 295 ELActor myEventLoop = ELActor.currentActor(); 296 ATActorMirror oldMirror = myEventLoop.getActorMirror(); 297 myEventLoop.setActorMirror(newActorMirror); 298 return oldMirror; 299 } 300 301 public ATActorMirror asActorMirror() throws XTypeMismatch { 302 return this; 303 } 304 305}