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

com.threerings.nexus.distrib.NexusObject Maven / Gradle / Ivy

The newest version!
//
// Nexus Core - a framework for developing distributed applications
// http://github.com/threerings/nexus/blob/master/LICENSE

package com.threerings.nexus.distrib;

import java.util.ArrayList;
import java.util.List;

import react.Signal;

import com.threerings.nexus.io.Streamable;

import static com.threerings.nexus.util.Log.log;

/**
 * The basis for all distributed information sharing in Nexus.
 */
public abstract class NexusObject
    implements Streamable, NexusService.ObjectResponse
{
    /**
     * A signal that is emitted if the subscription to this object is lost due to the object being
     * destroyed or due to the connection to the server that hosts this object being lost. The
     * exception delivered to the signal will be null if the object was destroyed or the cause of
     * the networking failure if an object is lost due to loss of network connection. This signal
     * will never be emitted on the hosting server, only on a subscribing client.
     */
    public final Signal onLost = Signal.create();

    /**
     * Returns this object's Nexus id. Only valid after the object has been registered with Nexus.
     */
    public int getId () {
        return _id;
    }

    /**
     * Returns the address of this object.
     */
    public Address getAddress () {
        if (this instanceof Keyed) {
            @SuppressWarnings("unchecked") Class clz = (Class)getClass();
            return Address.create(_sink.getHost(), clz, ((Keyed)this).getKey());
        } else if (this instanceof Singleton) {
            @SuppressWarnings("unchecked") Class clz = (Class)getClass();
            return Address.create(_sink.getHost(), clz);
        } else {
            return Address.create(_sink.getHost(), getId());
        }
    }

    /**
     * Reads the contents of this object from the supplied input.
     */
    public void readContents (Streamable.Input in) {
        _id = in.readInt();
        for (DAttribute attr : _attrs) attr.readContents(in);
    }

    /**
     * Writes the contents of this object to the supplied output.
     */
    public void writeContents (Streamable.Output out) {
        out.writeInt(_id);
        for (DAttribute attr : _attrs) attr.writeContents(out);
    }

    @Override // from NexusService.ObjectResponse
    public NexusObject[] getObjects () {
        return new NexusObject[] { this };
    }

    /**
     * Initializes this object with its id and event sink. This takes place when the object is
     * registered with dispatcher on its originating server, and when it is read off the network on
     * a subscribing client (though in this latter case the id is not changed).
     */
    protected void init (int id, EventSink sink) {
        _id = id;
        _sink = sink;
    }

    /**
     * Clears out this object's distributed id and event sink. Called by the object manager when
     * this object is unregistered.
     */
    protected void clear () {
        _id = 0;
        _sink = null;
    }

    /**
     * Registers this attribute with its owning object. This is called automatically by the
     * attributes' constructors.
     * @return the attribute's index in this object.
     */
    protected final short registerAttr (DAttribute attr) {
        int index = _attrs.size();
        _attrs.add(attr);
        return (short)index;
    }

    /**
     * Returns the distributed attribute at the specified index.
     */
    protected final  T getAttribute (int index) {
        @SuppressWarnings("unchecked") T attr = (T)_attrs.get(index);
        return attr;
    }

    /**
     * Requests that the supplied event be posted to this object.
     */
    protected void postEvent (NexusEvent event) {
        if (_id > 0) {
            assert(event.targetId == getId());
            _sink.postEvent(this, event);
        } else {
            log.warning("Requested to post event to unregistered object",
                        "event", event, new Exception());
        }
    }

    /**
     * Requests that a service call be posted to this object.
     */
    protected void postCall (short attrIndex, short methodId, Object[] args) {
        _sink.postCall(this, attrIndex, methodId, args);
    }

    /** Used by {@link #getAddress} for type jockeying. */
    private static class DummyKeyed extends NexusObject implements Keyed {
        public Comparable getKey () { return null; }
    }
    /** Used by {@link #getAddress} for type jockeying. */
    private static class DummySingle extends NexusObject implements Singleton {}

    /** The unique identifier for this object. This value is not available until the object has
     * been registered with the Nexus Manager. The id is unique with respect to the peer on which
     * this object was created and registered. */
    protected int _id;

    /** Handles the dispatch of events on this object. */
    protected EventSink _sink;

    /** All of this object's attributes. Attributes are added during object construction. */
    protected final List _attrs = new ArrayList();
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy