/* * Quasar: lightweight threads and actors for the JVM. * Copyright (c) 2013-2015, Parallel Universe Software Co. All rights reserved. * * This program and the accompanying materials are dual-licensed under * either the terms of the Eclipse Public License v1.0 as published by * the Eclipse Foundation * * or (per the licensee's choosing) * * under the terms of the GNU Lesser General Public License version 3.0 * as published by the Free Software Foundation. */ package co.paralleluniverse.actors; import co.paralleluniverse.fibers.SuspendExecution; import co.paralleluniverse.remote.RemoteChannelProxyFactoryService; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * This class should be extended by implementations of remote actors. * * @author pron */ public abstract class RemoteActor<Message> extends ActorImpl<Message> { private static final Logger LOG = LoggerFactory.getLogger(RemoteActor.class); private final transient ActorImpl<Message> actor; protected RemoteActor(ActorRef<Message> actor) { super(actor.getName(), RemoteChannelProxyFactoryService.create(actor.getImpl().mailbox(), ((Actor)actor.getImpl()).getGlobalId()), actor); this.actor = actor.getImpl(); } protected void handleAdminMessage(RemoteActorAdminMessage msg) { if (msg instanceof RemoteActorRegisterListenerAdminMessage) { actor.addLifecycleListener(((RemoteActorRegisterListenerAdminMessage) msg).getListener()); } else if (msg instanceof RemoteActorUnregisterListenerAdminMessage) { final RemoteActorUnregisterListenerAdminMessage unreg = (RemoteActorUnregisterListenerAdminMessage) msg; if (unreg.getObserver() != null) actor.removeObserverListeners(unreg.getObserver()); else actor.removeLifecycleListener(unreg.getListener()); } else if (msg instanceof RemoteActorInterruptAdminMessage) { actor.interrupt(); } else if (msg instanceof RemoteActorThrowInAdminMessage) { actor.throwIn(((RemoteActorThrowInAdminMessage) msg).getException()); } } public ActorImpl<Message> getActor() { return actor; } @Override protected void internalSend(Object message) throws SuspendExecution { actor.internalSend(message); } @Override protected void internalSendNonSuspendable(Object message) { actor.internalSendNonSuspendable(message); } @Override public boolean trySend(Message message) { internalSendNonSuspendable(message); return true; } @Override protected void addLifecycleListener(LifecycleListener listener) { internalSendNonSuspendable(new RemoteActorRegisterListenerAdminMessage(listener)); } @Override protected void removeLifecycleListener(LifecycleListener listener) { internalSendNonSuspendable(new RemoteActorUnregisterListenerAdminMessage(listener)); } @Override protected void removeObserverListeners(ActorRef observer) { internalSendNonSuspendable(new RemoteActorUnregisterListenerAdminMessage(observer)); } @Override protected void throwIn(RuntimeException e) { internalSendNonSuspendable(new RemoteActorThrowInAdminMessage(e)); } @Override public void interrupt() { internalSendNonSuspendable(new RemoteActorInterruptAdminMessage()); } protected static ActorImpl getImpl(ActorRef<?> actor) { return actor.getImpl(); } protected static abstract class RemoteActorAdminMessage implements java.io.Serializable { } private static class RemoteActorRegisterListenerAdminMessage extends RemoteActorAdminMessage { private final LifecycleListener listener; @Override public String toString() { return "RemoteActorListenerAdminMessage{" + "listener=" + listener + '}'; } public RemoteActorRegisterListenerAdminMessage(LifecycleListener listener) { this.listener = listener; } public LifecycleListener getListener() { return listener; } } private static class RemoteActorUnregisterListenerAdminMessage extends RemoteActorAdminMessage { private final ActorRef observer; private final LifecycleListener listener; public RemoteActorUnregisterListenerAdminMessage(ActorRef observer) { this.observer = observer; this.listener = null; } public RemoteActorUnregisterListenerAdminMessage(LifecycleListener listener) { this.listener = listener; this.observer = null; } public ActorRef getObserver() { return observer; } public LifecycleListener getListener() { return listener; } } private static class RemoteActorInterruptAdminMessage extends RemoteActorAdminMessage { } private static class RemoteActorThrowInAdminMessage extends RemoteActorAdminMessage { private final RuntimeException e; public RemoteActorThrowInAdminMessage(RuntimeException e) { this.e = e; } public RuntimeException getException() { return e; } } }