|
|||||||||
| PREV CLASS NEXT CLASS | FRAMES NO FRAMES | ||||||||
| SUMMARY: NESTED | FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD | ||||||||
java.lang.Objectcom.threerings.presents.dobj.DObject
public class DObject
The distributed object forms the foundation of the Presents system. All information shared among users of the system is done via distributed objects. A distributed object has a set of listeners. These listeners have access to the object or a proxy of the object and therefore have access to the data stored in the object's members at all times.
Additionally, an object has a set of subscribers. Subscribers manage the lifespan of the object; while a subscriber is subscribed, the listeners registered with an object will be notified of events. When the subscriber unsubscribes, the object becomes non-live and the listeners are no longer notified. Note: on the server, object subscription is merely a formality as all objects remain live all the time, so do not depend on event notifications ceasing when a subscriber has relinquished its subscription. Always unregister all listeners when they no longer need to hear from an object.
When there is any change to the the object's fields data, an event is generated which is dispatched to all listeners of the object, notifying them of that change and effecting that change to the copy of the object maintained at each client. In this way, both a repository of shared information and a mechanism for asynchronous notification are made available as a fundamental application building blocks.
To define what information is shared, an application creates a distributed object
declaration which is much like a class declaration except that it is transformed into a proper
derived class of DObject by a script. A declaration looks something like this:
public dclass RoomObject
{
public String description;
public int[] occupants;
}
which is converted into an actual Java class that looks like this:
public class RoomObject extends DObject
{
public String getDescription ()
{
// ...
}
public void setDescription (String description)
{
// ...
}
public int[] getOccupants ()
{
// ...
}
public void setOccupants (int[] occupants)
{
// ...
}
public void setOccupantsAt (int index, int value)
{
// ...
}
}
These method calls on the actual distributed object will result in the proper attribute change
events being generated and dispatched.
Note that distributed object fields can be any of the following set of primitive types:
Fields of type
boolean, byte, short, int, long, float, double
Boolean, Byte, Short, Integer, Long, Float, Double, String
boolean[], byte[], short[], int[], long[], float[], double[], String[]
Streamable can also be used.
| Field Summary | |
|---|---|
protected AccessController |
_controller
The entity that tells us if an event or subscription request should be allowed. |
protected boolean |
_deathWish
Indicates whether we want to be destroyed when our last subscriber is removed. |
protected Field[] |
_fields
An array of our fields, sorted for efficient lookup. |
protected static Map<Class<?>,Field[]> |
_ftable
Maintains a mapping of sorted field arrays for each distributed object class. |
protected Object[] |
_listeners
Our event listeners list. |
protected Object[] |
_locattrs
Any local attributes configured on this object or null. |
protected Object[] |
_locks
A list of outstanding locks. |
protected int |
_oid
Our object id. |
protected DObjectManager |
_omgr
A reference to our object manager. |
protected int |
_scount
Our subscriber count. |
protected Object[] |
_subs
Our subscribers list. |
protected boolean |
_tcancelled
Whether or not our nested transaction has been cancelled. |
protected int |
_tcount
The nesting depth of our current transaction. |
protected CompoundEvent |
_tevent
The compound event associated with our transaction, if we're currently in a transaction. |
protected static Comparator<Field> |
FIELD_COMP
Used to sort and search _fields. |
protected static Object[] |
NO_ATTRS
Simplifies code for objects that have no local attributes. |
| Constructor Summary | |
|---|---|
DObject()
|
|
| Method Summary | ||
|---|---|---|
boolean |
acquireLock(String name)
At times, an entity on the server may need to ensure that events it has queued up have made it through the event queue and are applied to their respective objects before a service may safely be undertaken again. |
|
void |
addListener(ChangeListener listener)
Adds an event listener to this object. |
|
void |
addListener(ChangeListener listener,
boolean weak)
Adds an event listener to this object. |
|
void |
addSubscriber(Subscriber<?> sub)
Don't call this function! |
|
|
addToSet(String setName,
T entry)
Request to have the specified item added to the specified DSet. |
|
void |
cancelTransaction()
Cancels the transaction in which this distributed object is involved. |
|
void |
changeAttribute(String name,
Object value)
Requests that the specified attribute be changed to the specified value. |
|
boolean |
checkPermissions(DEvent event)
Checks to ensure that this event which is about to be processed, has the appropriate permissions. |
|
boolean |
checkPermissions(Subscriber<?> sub)
Checks to ensure that the specified subscriber has access to this object. |
|
protected void |
clearLock(String name)
Don't call this function! |
|
protected void |
clearTransaction()
Removes this object from participation in any transaction in which it might be taking part. |
|
void |
commitTransaction()
Commits the transaction in which this distributed object is involved. |
|
void |
destroy()
Requests that this distributed object be destroyed. |
|
AccessController |
getAccessController()
Returns a reference to the access controller in use by this object or null if none has been configured. |
|
Object |
getAttribute(String name)
Looks up the named attribute and returns a reference to it. |
|
protected Field |
getField(String name)
Returns the Field with the specified name or null if there is none such. |
|
protected int |
getListenerIndex(ChangeListener listener)
Returns the index of the identified listener, or -1 if not found. |
|
|
getLocal(Class<T> key)
Retrieves a local attribute for the supplied key. |
|
List<Object> |
getLocals()
Returns an array containing our local attributes. |
|
DObjectManager |
getManager()
Returns the dobject manager under the auspices of which this object operates. |
|
int |
getOid()
Returns the object id of this object. |
|
|
getSet(String setName)
Get the DSet with the specified name. |
|
boolean |
inTransaction()
Returns true if this object is in the middle of a transaction or false if it is not. |
|
boolean |
isActive()
Returns true if this object is active and registered with the distributed object system. |
|
void |
notifyListeners(DEvent event)
Called by the distributed object manager after it has applied an event to this object. |
|
void |
notifyProxies(DEvent event)
Called by the distributed object manager after it has applied an event to this object. |
|
void |
postEvent(DEvent event)
Posts the specified event either to our dobject manager or to the compound event for which we are currently transacting. |
|
void |
postMessage(String name,
Object... args)
Posts a message event on this distributed object. |
|
void |
postMessage(Transport transport,
String name,
Object... args)
Posts a message event on this distributed object. |
|
void |
releaseLock(String name)
Queues up an event that when processed will release the lock of the specified name. |
|
void |
removeFromSet(String setName,
Comparable<?> key)
Request to have the specified key removed from the specified DSet. |
|
void |
removeListener(ChangeListener listener)
Removes an event listener from this object. |
|
void |
removeSubscriber(Subscriber<?> sub)
Don't call this function! |
|
protected void |
requestAttributeChange(String name,
Object value,
Object oldValue)
Called by derived instances when an attribute setter method was called. |
|
protected void |
requestAttributeChange(String name,
Object value,
Object oldValue,
Transport transport)
Called by derived instances when an attribute setter method was called. |
|
protected void |
requestElementUpdate(String name,
int index,
Object value,
Object oldValue)
Called by derived instances when an element updater method was called. |
|
protected void |
requestElementUpdate(String name,
int index,
Object value,
Object oldValue,
Transport transport)
Called by derived instances when an element updater method was called. |
|
protected
|
requestEntryAdd(String name,
DSet<T> set,
T entry)
Calls by derived instances when a set adder method was called. |
|
protected
|
requestEntryRemove(String name,
DSet<T> set,
Comparable<?> key)
Calls by derived instances when a set remover method was called. |
|
protected
|
requestEntryUpdate(String name,
DSet<T> set,
T entry)
Calls by derived instances when a set updater method was called. |
|
protected
|
requestEntryUpdate(String name,
DSet<T> set,
T entry,
Transport transport)
Calls by derived instances when a set updater method was called. |
|
protected void |
requestOidAdd(String name,
int oid)
Calls by derived instances when an oid adder method was called. |
|
protected void |
requestOidRemove(String name,
int oid)
Calls by derived instances when an oid remover method was called. |
|
void |
setAccessController(AccessController controller)
Provides this object with an entity that can be used to validate subscription requests and events before they are processed. |
|
void |
setAttribute(String name,
Object value)
Sets the named attribute to the specified value. |
|
void |
setDestroyOnLastSubscriberRemoved(boolean deathWish)
Instructs this object to request to have a fork stuck in it when its last subscriber is removed. |
|
|
setLocal(Class<T> key,
T attr)
Configures a local attribute on this object. |
|
void |
setManager(DObjectManager omgr)
Don't call this function! |
|
void |
setOid(int oid)
Don't call this function. |
|
void |
startTransaction()
Begins a transaction on this distributed object. |
|
String |
toString()
|
|
protected void |
toString(StringBuilder buf)
Generates a string representation of this object. |
|
void |
updateSet(String setName,
DSet.Entry entry)
Request to have the specified item updated in the specified DSet. |
|
String |
which()
Generates a concise string representation of this object. |
|
protected void |
which(StringBuilder buf)
Used to briefly describe this distributed object. |
|
| Methods inherited from class java.lang.Object |
|---|
clone, equals, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait |
| Field Detail |
|---|
protected int _oid
protected transient Field[] _fields
protected transient DObjectManager _omgr
protected transient AccessController _controller
protected transient Object[] _locks
protected transient Object[] _subs
protected transient Object[] _listeners
protected transient int _scount
protected transient CompoundEvent _tevent
protected transient int _tcount
protected transient boolean _tcancelled
protected transient boolean _deathWish
protected transient Object[] _locattrs
protected static Map<Class<?>,Field[]> _ftable
protected static final Comparator<Field> FIELD_COMP
_fields.
protected static final Object[] NO_ATTRS
| Constructor Detail |
|---|
public DObject()
| Method Detail |
|---|
public int getOid()
public DObjectManager getManager()
null if the object is not active.
public void addSubscriber(Subscriber<?> sub)
objectAvailable or to a listener callback).
DObjectManager.subscribeToObject(int, com.threerings.presents.dobj.Subscriber) public void removeSubscriber(Subscriber<?> sub)
objectAvailable or to a listener callback).
DObjectManager.unsubscribeFromObject(int, com.threerings.presents.dobj.Subscriber) public void setDestroyOnLastSubscriberRemoved(boolean deathWish)
public void addListener(ChangeListener listener)
Note that the entity adding itself as a listener should have obtained the object
reference by subscribing to it or should be acting on behalf of some other entity that
subscribed to the object, and that it must be sure to remove itself from the
listener list (via removeListener(com.threerings.presents.dobj.ChangeListener)) when it is done because unsubscribing from the
object (done by whatever entity subscribed in the first place) is not guaranteed to result
in the listeners added through that subscription being automatically removed (in most cases,
they definitely will not be removed).
listener - the listener to be added.EventListener,
AttributeChangeListener,
SetListener,
OidListListener
public void addListener(ChangeListener listener,
boolean weak)
Note that the entity adding itself as a listener should have obtained the object
reference by subscribing to it or should be acting on behalf of some other entity that
subscribed to the object, and that it must be sure to remove itself from the
listener list (via removeListener(com.threerings.presents.dobj.ChangeListener)) when it is done because unsubscribing from the
object (done by whatever entity subscribed in the first place) is not guaranteed to result
in the listeners added through that subscription being automatically removed (in most cases,
they definitely will not be removed).
listener - the listener to be added.weak - if true, retain only a weak reference to the listener (do not prevent the
listener from being garbage-collected).EventListener,
AttributeChangeListener,
SetListener,
OidListListenerpublic void removeListener(ChangeListener listener)
listener - the listener to be removed.public void setAccessController(AccessController controller)
public AccessController getAccessController()
public final <T extends DSet.Entry> DSet<T> getSet(String setName)
public <T extends DSet.Entry> void addToSet(String setName,
T entry)
public void updateSet(String setName,
DSet.Entry entry)
public void removeFromSet(String setName,
Comparable<?> key)
public boolean acquireLock(String name)
releaseLock) which will queue up a final event, the processing of which will
release the lock. Thus the lock will not be released until all of the previously generated
events have been processed. If the service is invoked again before that lock is released,
the associated call to acquireLock will fail and the code can respond
accordingly. An object may have any number of outstanding locks as long as they each have a
unique name.
name - the name of the lock to acquire.
releaseLock(java.lang.String)public void releaseLock(String name)
acquireLock(java.lang.String)protected void clearLock(String name)
acquireLock you should be using releaseLock.
acquireLock(java.lang.String),
releaseLock(java.lang.String)public void destroy()
public boolean checkPermissions(Subscriber<?> sub)
AccessController has been
specified for this object, it will be used to determine whether or not to allow the
subscription request. If no controller is set, the subscription will be allowed.
sub - the subscriber that will subscribe to this object.
public boolean checkPermissions(DEvent event)
AccessController has been specified for this object, it will be
used to determine whether or not to allow the even dispatch. If no controller is set, all
events are allowed.
event - the event that will be dispatched, object permitting.
public void notifyListeners(DEvent event)
event - the event that was just applied.public void notifyProxies(DEvent event)
event - the event that was just applied.
public void changeAttribute(String name,
Object value)
throws ObjectAccessException
ObjectAccessException
public void setAttribute(String name,
Object value)
throws ObjectAccessException
ObjectAccessException
public Object getAttribute(String name)
throws ObjectAccessException
ObjectAccessException
public void postMessage(String name,
Object... args)
public void postMessage(Transport transport,
String name,
Object... args)
transport - a hint as to the type of transport desired for the message.public void postEvent(DEvent event)
public final boolean isActive()
DObjectManager.createObject it will be active until
such time as it is destroyed.
public void setManager(DObjectManager omgr)
RootDObjectManager.registerObject(DObject)public void setOid(int oid)
RootDObjectManager.registerObject(DObject)
public <T> void setLocal(Class<T> key,
T attr)
Also note that it is illegal to replace the value of a local attribute. Attempting to set a local attribute that already contains a value will fail. This is intended to catch programmer error as early as possible. You may clear a local attribute by setting it to null and then it can be set to a new value.
Lastly, note that key polymorphism is implemented to allow a lower level framework to define a local attribute and users of that framework to extend the attribute class and have it returned whether the derived or base class is used to look up the attribute. For example:
class BaseLocalAttr {
public int foo;
}
class DerivedLocalAttr extends BaseLocalAttr {
public int bar;
}
// simple usage
DObject o1 = new DObject();
BaseLocalAttr base = new BaseLocalAttr();
o1.setLocal(BaseLocalAttr.class, base);
assertSame(o1.getLocal(BaseLocalAttr.class), base); // true
// polymorphic usage
DObject o2 = new DObject();
DerivedLocalAttr derived = new DerivedLocalAttr();
o2.setLocal(DerivedLocalAttr.class, derived);
BaseLocalAttr upcasted = derived;
assertSame(o2.getLocal(DerivedLocalAttr.class), derived); // true
assertSame(o2.getLocal(BaseLocalAttr.class), upcasted); // true
// cannot overwrite already set attribute
DObject o3 = new DObject();
o3.setLocal(DerivedLocalAttr.class, derived);
o3.setLocal(DerivedLocalAttr.class, new DerivedLocalAttr()); // will fail
o3.setLocal(BaseLocalAttr.class, new BaseLocalAttr()); // will fail
IllegalStateException - thrown if an attempt is made to set a local attribute that
already contains a non-null value with any non-null value.public <T> T getLocal(Class<T> key)
setLocal(java.lang.Class, T) for
information on key polymorphism. Returns null if no attribute is found that matches the
supplied key.
public List<Object> getLocals()
public String which()
public String toString()
toString in class Objectprotected void which(StringBuilder buf)
protected void toString(StringBuilder buf)
public void startTransaction()
When the transaction is complete, the caller must call commitTransaction() or
CompoundEvent.commit() to commit the transaction and release the object back to its
normal non-transacting state. If the caller decides not to commit their transaction, they
must call cancelTransaction() or CompoundEvent.cancel() to cancel the
transaction. Failure to do so will cause the pooch to be totally screwed.
Note: like all other distributed object operations, transactions are not thread safe. It is expected that a single thread will handle all distributed object operations and that thread will begin and complete a transaction before giving up control to unknown code which might try to operate on the transacting distributed object.
Note also: if the object is already engaged in a transaction, a transaction participant
count will be incremented to note that an additional call to commitTransaction() is
required before the transaction should actually be committed. Thus every call to
startTransaction() must be accompanied by a call to either commitTransaction()
or cancelTransaction(). Additionally, if any transaction participant cancels the
transaction, the entire transaction is cancelled for all participants, regardless of whether
the other participants attempted to commit the transaction.
public void commitTransaction()
CompoundEvent.commit()public boolean inTransaction()
public void cancelTransaction()
CompoundEvent.cancel()protected void clearTransaction()
protected void requestAttributeChange(String name,
Object value,
Object oldValue)
protected void requestAttributeChange(String name,
Object value,
Object oldValue,
Transport transport)
protected void requestElementUpdate(String name,
int index,
Object value,
Object oldValue)
protected void requestElementUpdate(String name,
int index,
Object value,
Object oldValue,
Transport transport)
protected void requestOidAdd(String name,
int oid)
protected void requestOidRemove(String name,
int oid)
protected <T extends DSet.Entry> void requestEntryAdd(String name,
DSet<T> set,
T entry)
protected <T extends DSet.Entry> void requestEntryRemove(String name,
DSet<T> set,
Comparable<?> key)
protected <T extends DSet.Entry> void requestEntryUpdate(String name,
DSet<T> set,
T entry)
protected <T extends DSet.Entry> void requestEntryUpdate(String name,
DSet<T> set,
T entry,
Transport transport)
protected final Field getField(String name)
Field with the specified name or null if there is none such.
protected int getListenerIndex(ChangeListener listener)
|
|||||||||
| PREV CLASS NEXT CLASS | FRAMES NO FRAMES | ||||||||
| SUMMARY: NESTED | FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD | ||||||||