Let's just have SafeSubscriber take two callbacks instead of forcing everyone

to screw around with SubscriberAdapter.


git-svn-id: svn+ssh://src.earth.threerings.net/narya/trunk@5719 542714f4-19e9-0310-aa3c-eee0fc999fb1
This commit is contained in:
Michael Bayne
2009-04-15 00:22:24 +00:00
parent 202f6bba81
commit b160aa944f
3 changed files with 35 additions and 38 deletions
@@ -7,8 +7,6 @@ import com.threerings.presents.client.BasicDirector;
import com.threerings.presents.client.Client; import com.threerings.presents.client.Client;
import com.threerings.presents.client.ClientEvent; import com.threerings.presents.client.ClientEvent;
import com.threerings.presents.dobj.ObjectAccessError; import com.threerings.presents.dobj.ObjectAccessError;
import com.threerings.presents.dobj.Subscriber;
import com.threerings.presents.dobj.SubscriberAdapter;
import com.threerings.presents.util.SafeSubscriber; import com.threerings.presents.util.SafeSubscriber;
import com.threerings.bureau.data.AgentObject; import com.threerings.bureau.data.AgentObject;
@@ -53,13 +51,10 @@ public class BureauDirector extends BasicDirector
*/ */
protected function createAgentFromId (agentId :int) :void protected function createAgentFromId (agentId :int) :void
{ {
var delegator :Subscriber =
new SubscriberAdapter(objectAvailable, requestFailed);
log.info("Subscribing to object", "agentId", agentId); log.info("Subscribing to object", "agentId", agentId);
var subscriber :SafeSubscriber = var subscriber :SafeSubscriber =
new SafeSubscriber(agentId, delegator); new SafeSubscriber(agentId, objectAvailable, requestFailed);
_subscribers.put(agentId, subscriber); _subscribers.put(agentId, subscriber);
subscriber.subscribe(_ctx.getDObjectManager()); subscriber.subscribe(_ctx.getDObjectManager());
} }
@@ -55,28 +55,27 @@ public class SafeObjectManager
_failed = failed; _failed = failed;
} }
/** /**
* Safely requests the given object from the manager. If an <code>available</code> callback was * Safely requests the given object from the manager. If an <code>available</code> callback was
* provided to the constructor, it will be invoked when the request is fulfilled. If a * provided to the constructor, it will be invoked when the request is fulfilled. If a
* <code>failed</code> callback was provided, it will be invoked if the request fails. After * <code>failed</code> callback was provided, it will be invoked if the request fails. After
* and only after the request succeeds, <code>getObj</code> will return the object when called * and only after the request succeeds, <code>getObj</code> will return the object when called
* with this id. The optional callbacks must match the signatures of the ones from * with this id. The optional callbacks must match the signatures of the ones from
* <code>Subscriber</code>. If provided, they will be called in addition to the ones provided to * <code>Subscriber</code>. If provided, they will be called in addition to the ones provided
* <code>SafeObjectManager</code>. * to <code>SafeObjectManager</code>.
*
* @param oid the id of the object to request. * @param oid the id of the object to request.
* @param available an optional callback to be invoked when the object is ready * @param available an optional callback to be invoked when the object is ready
* @param failed an optional callback to be invoked if the request fails * @param failed an optional callback to be invoked if the request fails
*/ */
public function subscribe ( public function subscribe (oid :int, available :Function=null, failed :Function=null) :void
oid :int, available :Function=null, failed :Function=null) :void
{ {
if (_entries[oid] != null ) { if (_entries[oid] != null ) {
_log.warning("Object already subscribed", "oid", oid); _log.warning("Object already subscribed", "oid", oid);
return; return;
} }
var sub :SafeSubscriber = new SafeSubscriber(oid, _adapter); var sub :SafeSubscriber = new SafeSubscriber(oid, onAvailable, onFailed);
var entry :Entry = new Entry(sub); var entry :Entry = new Entry(sub);
entry.availableFn = available; entry.availableFn = available;
entry.failedFn = failed; entry.failedFn = failed;
@@ -86,8 +85,9 @@ public class SafeObjectManager
} }
/** /**
* Safely notifies the manager that an object is no longer needed. The <code>getObj</code> * Safely notifies the manager that an object is no longer needed. The <code>getObj</code>
* call will subsequently return null for this id. * call will subsequently return null for this id.
*
* @param oid the id of the object that is no longer needed * @param oid the id of the object that is no longer needed
*/ */
public function unsubscribe (oid :int) :void public function unsubscribe (oid :int) :void
@@ -100,7 +100,7 @@ public class SafeObjectManager
_log.debug("Unsubscribing", "sub", entry.sub); _log.debug("Unsubscribing", "sub", entry.sub);
if (entry.obj != null) { if (entry.obj != null) {
entry.obj.removeListener(_objectDeathListenerAdapter); entry.obj.removeListener(_odlist);
} }
if (!entry.destroyed && !entry.failed) { if (!entry.destroyed && !entry.failed) {
entry.sub.unsubscribe(_omgr); entry.sub.unsubscribe(_omgr);
@@ -130,9 +130,9 @@ public class SafeObjectManager
} }
/** /**
* Accesses an object. This returns non-null if the object corresponding to the id has been * Accesses an object. This returns non-null if the object corresponding to the id has been
* subscribed using <code>subscribe</code> and the subscription was completed successfully. It * subscribed using <code>subscribe</code> and the subscription was completed successfully. It
* will return null if the subscription has not yet succeeded or the object has been * will return null if the subscription has not yet succeeded or the object has been
* unsubscribed using <code>unsubscribe</code> or <code>unsubscribeAll</code>. * unsubscribed using <code>unsubscribe</code> or <code>unsubscribeAll</code>.
*/ */
public function getObj (oid :int) :DObject public function getObj (oid :int) :DObject
@@ -146,30 +146,27 @@ public class SafeObjectManager
} }
/** Notifies the manager that an object subscription request has succeeded */ /** Notifies the manager that an object subscription request has succeeded */
protected function available (obj :DObject) :void protected function onAvailable (obj :DObject) :void
{ {
var entry :Entry = _entries[obj.getOid()]; var entry :Entry = _entries[obj.getOid()];
if (entry == null) { if (entry == null) {
_log.warning("Object available without request", "obj", obj.which()); _log.warning("Object available without request", "obj", obj.which());
} else { } else {
_log.debug("Object now available", "obj", obj.which()); _log.debug("Object now available", "obj", obj.which());
entry.obj = obj; entry.obj = obj;
} }
obj.addListener(_objectDeathListenerAdapter); obj.addListener(_odlist);
if (_available != null) { if (_available != null) {
_available(obj); _available(obj);
} }
if (entry.availableFn != null) { if (entry.availableFn != null) {
entry.availableFn(obj); entry.availableFn(obj);
} }
} }
/** Notifies the manager that an object subscription request has failed */ /** Notifies the manager that an object subscription request has failed */
protected function failed (oid :int, cause :ObjectAccessError) :void protected function onFailed (oid :int, cause :ObjectAccessError) :void
{ {
var entry :Entry = _entries[oid]; var entry :Entry = _entries[oid];
if (entry == null) { if (entry == null) {
@@ -194,7 +191,7 @@ public class SafeObjectManager
protected function destroyed (event :ObjectDestroyedEvent) :void protected function destroyed (event :ObjectDestroyedEvent) :void
{ {
var oid :int = event.getTargetOid(); var oid :int = event.getTargetOid();
var entry :Entry = _entries[oid] as Entry; var entry :Entry = _entries[oid] as Entry;
if (entry == null) { if (entry == null) {
_log.warning("Unsubscribed object notified of destroy", "oid", oid); _log.warning("Unsubscribed object notified of destroy", "oid", oid);
@@ -211,9 +208,7 @@ public class SafeObjectManager
protected var _log :Log; protected var _log :Log;
protected var _available :Function; protected var _available :Function;
protected var _failed :Function; protected var _failed :Function;
protected var _adapter :SubscriberAdapter = new SubscriberAdapter(available, failed); protected var _odlist :ObjectDeathListenerAdapter = new ObjectDeathListenerAdapter(destroyed);
protected var _objectDeathListenerAdapter :ObjectDeathListenerAdapter =
new ObjectDeathListenerAdapter(destroyed);
protected var _entries :Dictionary = new Dictionary(); protected var _entries :Dictionary = new Dictionary();
} }
} }
@@ -37,9 +37,14 @@ public class SafeSubscriber implements Subscriber
{ {
/** /**
* Creates a safe subscriber for the specified distributed object which will interact with the * Creates a safe subscriber for the specified distributed object which will interact with the
* specified subscriber. * supplied callback functions.
*
* @param onAvailable a function to be called when the object in question is available. Looks
* like: function (obj :DObject) :void
* @param onFailure a function to be called if the subscription request fails. Looks like:
* function (oid :int, error :ObjectAccessError) :void
*/ */
public function SafeSubscriber (oid :int, subscriber :Subscriber) public function SafeSubscriber (oid :int, onAvailable :Function, onFailure :Function)
{ {
// make sure they're not fucking us around // make sure they're not fucking us around
if (oid <= 0) { if (oid <= 0) {
@@ -50,7 +55,8 @@ public class SafeSubscriber implements Subscriber
} }
_oid = oid; _oid = oid;
_subscriber = subscriber; _onAvailable = onAvailable;
_onFailure = onFailure;
} }
/** /**
@@ -79,7 +85,7 @@ public class SafeSubscriber implements Subscriber
if (_object != null) { if (_object != null) {
log.warning("Incroyable! A safesub has an object and was non-active!? " + this); log.warning("Incroyable! A safesub has an object and was non-active!? " + this);
// make do in the face of insanity // make do in the face of insanity
_subscriber.objectAvailable(_object); _onAvailable(_object);
return; return;
} }
@@ -171,7 +177,7 @@ public class SafeSubscriber implements Subscriber
// otherwise the air is fresh and clean and we can do our job // otherwise the air is fresh and clean and we can do our job
_object = object; _object = object;
_subscriber.objectAvailable(object); _onAvailable(object);
} }
// documentation inherited from interface // documentation inherited from interface
@@ -189,7 +195,7 @@ public class SafeSubscriber implements Subscriber
// deactivate ourselves as we never got our object (and thus the real subscriber need // deactivate ourselves as we never got our object (and thus the real subscriber need
// not call unsubscribe()) // not call unsubscribe())
_active = false; _active = false;
_subscriber.requestFailed(oid, cause); _onFailure(oid, cause);
} }
} }
@@ -202,7 +208,8 @@ public class SafeSubscriber implements Subscriber
} }
protected var _oid :int protected var _oid :int
protected var _subscriber :Subscriber; protected var _onAvailable :Function;
protected var _onFailure :Function;
protected var _object :DObject;; protected var _object :DObject;;
protected var _active :Boolean; protected var _active :Boolean;
protected var _pending :Boolean; protected var _pending :Boolean;