All Downloads are FREE. Search and download functionalities are using the official Maven repository.

co.paralleluniverse.actors.behaviors.Server Maven / Gradle / Ivy

/*
 * Quasar: lightweight threads and actors for the JVM.
 * Copyright (c) 2013-2014, 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.behaviors;

import co.paralleluniverse.actors.ActorRef;
import co.paralleluniverse.actors.LocalActor;
import static co.paralleluniverse.actors.behaviors.RequestReplyHelper.from;
import static co.paralleluniverse.actors.behaviors.RequestReplyHelper.makeId;
import co.paralleluniverse.fibers.SuspendExecution;
import co.paralleluniverse.strands.Timeout;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

/**
 * An interface to a {@link ServerActor}.
 *
 * @author pron
 */
public class Server extends Behavior {
    private volatile long defaultTimeoutNanos = -1;

    /**
     * If {@code actor} is known to be a {@link ServerActor}, creates a new {@link Server} interface to it.
     * Normally, you don't use this constructor, but the {@code Server} instance returned by {@link ServerActor#spawn() }.
     *
     * @param actor a {@link ServerActor}
     */
    public Server(ActorRef actor) {
        super(actor);
    }

    /**
     * Sets a default timeout for non-timed {@link #call(Object) call}s on this server reference.
     * Non-timed calls that take longer than the default timeout, will throw a {@link TimeoutException}
     * wrapped in a {@link RuntimeException}. Timed calls (those that take a timeout parameter) will not be affected.
     * 

* This method only affects calls made through this particular server actor reference and not calls to the same server actor * through other references. *

* This method has nothing to do with {@link ServerActor#setTimeout(long, TimeUnit) ServerActor.setTimeout} * * @param timeout the timeout duration * @param unit the time unit of the timeout, or {@code null} to unset. */ public void setDefaultTimeout(long timeout, TimeUnit unit) { if (unit == null) defaultTimeoutNanos = -1; else defaultTimeoutNanos = unit.toNanos(timeout); } /** * Sends a synchronous request to the actor, and awaits a response. * This method will wait indefinitely for the actor to respond unless a default timeout has been set for this * server reference with {@link #setDefaultTimeout(long, TimeUnit) setDefaultTimeout}. *

* This method may be safely called by actors and non-actor strands alike. * * @param m the request * @return the value sent as a response from the actor * @throws RuntimeException if the actor encountered an error while processing the request */ public final V call(CallMessage m) throws InterruptedException, SuspendExecution { final long timeout = defaultTimeoutNanos; try { if (timeout > 0) return call(m, timeout, TimeUnit.NANOSECONDS); else return call(m, 0, null); } catch (TimeoutException ex) { if (timeout >= 0) throw new RuntimeException(ex); else throw new AssertionError(ex); } } /** * Sends a synchronous request to the actor, and awaits a response, but no longer than the given timeout. *

* This method may be safely called by actors and non-actor strands alike. * * @param m the request * @param timeout the maximum duration to wait for a response. * @param unit the time unit of the timeout * @return the value sent as a response from the actor * @throws RuntimeException if the actor encountered an error while processing the request * @throws TimeoutException if the timeout expires before a response has been received. */ public final V call(CallMessage m, long timeout, TimeUnit unit) throws TimeoutException, InterruptedException, SuspendExecution { final V res = RequestReplyHelper.call(this, new ServerRequest(from(), null, MessageType.CALL, m), timeout, unit); return res; } /** * Sends a synchronous request to the actor, and awaits a response, but no longer than the given timeout. *

* This method may be safely called by actors and non-actor strands alike. * * @param m the request * @param timeout the method will not block for longer than the amount remaining in the {@link Timeout} * @return the value sent as a response from the actor * @throws RuntimeException if the actor encountered an error while processing the request * @throws TimeoutException if the timeout expires before a response has been received. */ public final V call(CallMessage m, Timeout timeout) throws TimeoutException, InterruptedException, SuspendExecution { return call(m, timeout.nanosLeft(), TimeUnit.NANOSECONDS); } /** * Sends an asynchronous request to the actor and returns immediately (may block until there's room available in the actor's mailbox). * * @param m the request */ public final void cast(CastMessage m) throws SuspendExecution { this.send(new ServerRequest(LocalActor.self(), makeId(), MessageType.CAST, m)); } // public static void cast(ActorRef server, Object m) throws SuspendExecution { // server.send(new ServerRequest(ActorRef.self(), makeId(), MessageType.CAST, m)); // } @Override public String toString() { return "Server{" + super.toString() + "}"; } enum MessageType { CALL, CAST }; static class ServerRequest extends RequestMessage { private final MessageType type; private final Object message; public ServerRequest(ActorRef sender, Object id, MessageType type, Object message) { super(sender, id); this.type = type; this.message = message; } public MessageType getType() { return type; } public Object getMessage() { return message; } } }