Search in sources :

Example 1 with MessageProcessor

use of co.paralleluniverse.actors.MessageProcessor in project quasar by puniverse.

the class RequestReplyHelper method call.

/**
 * Sends a request message to an actor, awaits a response value (but no longer than the given timeout) and returns it.
 * This method can be called by any code, even non-actor code.
 * If the actor responds with an error message, a {@link RuntimeException} will be thrown by this method.
 * <br/>
 * The message's {@code id} and {@code from} properties may be left unset.
 * <p/>
 * This method should be used as in the following example (assuming a {@code String} return value:
 * <pre> {@code
 * String res = call(actor, new MyRequest());
 * }</pre>
 * In the example, {@code MyRequest} extends {@link RequestMessage}. Note how the result of the {@link #from() from} method is passed to the
 * request's constructor, but the message ID isn't.
 *
 * @param <V>     the return value's type
 * @param actor   the actor to which the request is sent
 * @param timeout the maximum duration to wait for a response
 * @param unit    the time unit of the timeout
 * @return the value sent by the actor as a response
 * @throws RuntimeException     if the actor responds with an error message, its contained exception will be thrown, possibly wrapped by a {@link RuntimeException}.
 * @throws TimeoutException     if the timeout expires before a response is received from the actor.
 * @throws InterruptedException
 */
public static <V> V call(final ActorRef actor, RequestMessage<V> m, long timeout, TimeUnit unit) throws TimeoutException, InterruptedException, SuspendExecution {
    assert !actor.equals(LocalActor.self()) : "Can't \"call\" self - deadlock guaranteed";
    if (m.getFrom() == null || LocalActor.isInstance(m.getFrom(), TempActor.class))
        m.setFrom(from());
    final boolean tmpActor = m.getFrom() instanceof TempActorRef;
    final Actor currentActor = tmpActor ? (Actor) ((TempActorRef) m.getFrom()).getImpl() : Actor.currentActor();
    assert currentActor != null;
    currentActor.link(actor);
    if (m.getId() == null)
        m.setId(new Object());
    final Object id = m.getId();
    final SelectiveReceiveHelper<Object> helper = new SelectiveReceiveHelper<Object>(currentActor) {

        @Override
        protected void handleLifecycleMessage(LifecycleMessage m) {
            if (m instanceof ExitMessage) {
                final ExitMessage exit = (ExitMessage) m;
                if (Objects.equals(exit.getActor(), actor) && exit.getWatch() == null)
                    throw Exceptions.rethrow(exit.getCause());
            }
            super.handleLifecycleMessage(m);
        }
    };
    try {
        actor.sendSync(m);
        final ResponseMessage response = (ResponseMessage) helper.receive(timeout, unit, new MessageProcessor<Object, Object>() {

            @Override
            public Object process(Object m) throws SuspendExecution, InterruptedException {
                return (m instanceof ResponseMessage && id.equals(((ResponseMessage) m).getId())) ? m : null;
            }
        });
        // no need to unlink in case of receiver death, so not done in finally block
        currentActor.unlink(actor);
        if (response instanceof ErrorResponseMessage)
            throw Exceptions.rethrow(((ErrorResponseMessage) response).getError());
        return ((ValueResponseMessage<V>) response).getValue();
    } catch (InterruptedException e) {
        if (tmpActor)
            currentActor.checkThrownIn();
        throw e;
    } finally {
    // if (tmpActor)
    // ((TempActor) m.getFrom()).done();
    }
}
Also used : SelectiveReceiveHelper(co.paralleluniverse.actors.SelectiveReceiveHelper) ExitMessage(co.paralleluniverse.actors.ExitMessage) MessageProcessor(co.paralleluniverse.actors.MessageProcessor) LocalActor(co.paralleluniverse.actors.LocalActor) Actor(co.paralleluniverse.actors.Actor) LifecycleMessage(co.paralleluniverse.actors.LifecycleMessage)

Example 2 with MessageProcessor

use of co.paralleluniverse.actors.MessageProcessor in project quasar by puniverse.

the class FiniteStateMachineTest method testStates.

@Test
public void testStates() throws Exception {
    final AtomicBoolean success = new AtomicBoolean();
    ActorRef<Object> a = new FiniteStateMachineActor() {

        @Override
        protected SuspendableCallable<SuspendableCallable> initialState() {
            return new SuspendableCallable<SuspendableCallable>() {

                public SuspendableCallable run() throws SuspendExecution, InterruptedException {
                    return state1();
                }
            };
        }

        private SuspendableCallable<SuspendableCallable> state1() throws SuspendExecution, InterruptedException {
            return receive(new MessageProcessor<Object, SuspendableCallable<SuspendableCallable>>() {

                @Override
                public SuspendableCallable<SuspendableCallable> process(Object m) throws SuspendExecution, InterruptedException {
                    if ("a".equals(m))
                        return new SuspendableCallable<SuspendableCallable>() {

                            public SuspendableCallable run() throws SuspendExecution, InterruptedException {
                                return state2();
                            }
                        };
                    return null;
                }
            });
        }

        private SuspendableCallable<SuspendableCallable> state2() throws SuspendExecution, InterruptedException {
            return receive(new MessageProcessor<Object, SuspendableCallable<SuspendableCallable>>() {

                @Override
                public SuspendableCallable<SuspendableCallable> process(Object m) throws SuspendExecution, InterruptedException {
                    if ("b".equals(m)) {
                        success.set(true);
                        return TERMINATE;
                    }
                    return null;
                }
            });
        }
    }.spawn();
    a.send("b");
    a.send("a");
    LocalActor.join(a, 100, TimeUnit.MILLISECONDS);
    assertTrue(success.get());
}
Also used : AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) SuspendExecution(co.paralleluniverse.fibers.SuspendExecution) MessageProcessor(co.paralleluniverse.actors.MessageProcessor) SuspendableCallable(co.paralleluniverse.strands.SuspendableCallable) Test(org.junit.Test)

Aggregations

MessageProcessor (co.paralleluniverse.actors.MessageProcessor)2 Actor (co.paralleluniverse.actors.Actor)1 ExitMessage (co.paralleluniverse.actors.ExitMessage)1 LifecycleMessage (co.paralleluniverse.actors.LifecycleMessage)1 LocalActor (co.paralleluniverse.actors.LocalActor)1 SelectiveReceiveHelper (co.paralleluniverse.actors.SelectiveReceiveHelper)1 SuspendExecution (co.paralleluniverse.fibers.SuspendExecution)1 SuspendableCallable (co.paralleluniverse.strands.SuspendableCallable)1 AtomicBoolean (java.util.concurrent.atomic.AtomicBoolean)1 Test (org.junit.Test)1