Widening.

git-svn-id: svn+ssh://src.earth.threerings.net/narya/trunk@5718 542714f4-19e9-0310-aa3c-eee0fc999fb1
This commit is contained in:
Michael Bayne
2009-04-15 00:13:29 +00:00
parent e1b29dbf6f
commit 202f6bba81
@@ -29,28 +29,24 @@ import com.threerings.presents.dobj.ObjectAccessError;
import com.threerings.presents.dobj.Subscriber; import com.threerings.presents.dobj.Subscriber;
/** /**
* A class that safely handles the asynchronous subscription to a * A class that safely handles the asynchronous subscription to a distributed object when it is not
* distributed object when it is not know if the subscription will * know if the subscription will complete before the subscriber decides they no longer wish to be
* complete before the subscriber decides they no longer wish to be
* subscribed. * subscribed.
*/ */
public class SafeSubscriber implements Subscriber public class SafeSubscriber implements Subscriber
{ {
private static const log :Log = Log.getLog(SafeSubscriber);
/** /**
* Creates a safe subscriber for the specified distributed object * Creates a safe subscriber for the specified distributed object which will interact with the
* which will interact with the specified subscriber. * specified subscriber.
*/ */
public function SafeSubscriber (oid :int, subscriber :Subscriber) public function SafeSubscriber (oid :int, subscriber :Subscriber)
{ {
// make sure they're not fucking us around // make sure they're not fucking us around
if (oid <= 0) { if (oid <= 0) {
throw new ArgumentError( throw new ArgumentError("Invalid oid provided to safesub [oid=" + oid + "]");
"Invalid oid provided to safesub [oid=" + oid + "]");
} }
if (subscriber == null) { if (subscriber == null) {
throw new ArgumentError( throw new ArgumentError("Null subscriber provided to safesub [oid=" + oid + "]");
"Null subscriber provided to safesub [oid=" + oid + "]");
} }
_oid = oid; _oid = oid;
@@ -58,8 +54,8 @@ public class SafeSubscriber implements Subscriber
} }
/** /**
* Returns true if we are currently subscribed to our object (or in * Returns true if we are currently subscribed to our object (or in the process of obtaining a
* the process of obtaining a subscription). * subscription).
*/ */
public function isActive () :Boolean public function isActive () :Boolean
{ {
@@ -72,54 +68,50 @@ public class SafeSubscriber implements Subscriber
public function subscribe (omgr :DObjectManager) :void public function subscribe (omgr :DObjectManager) :void
{ {
if (_active) { if (_active) {
log.warning("Active safesub asked to resubscribe " + this + "."); log.warning("Active safesub asked to resubscribe " + this);
return; return;
} }
// note that we are now again in the "wishing to be subscribed" state // note that we are now again in the "wishing to be subscribed" state
_active = true; _active = true;
// make sure we dont have an object reference (which should be // make sure we dont have an object reference (which should be logically impossible)
// logically impossible)
if (_object != null) { if (_object != null) {
log.warning("Incroyable! A safesub has an object and was " + log.warning("Incroyable! A safesub has an object and was non-active!? " + this);
"non-active!? " + this + ".");
// make do in the face of insanity // make do in the face of insanity
_subscriber.objectAvailable(_object); _subscriber.objectAvailable(_object);
return; return;
} }
if (_pending) { if (_pending) {
// we were previously asked to subscribe, then they asked to // we were previously asked to subscribe, then they asked to unsubscribe and now
// unsubscribe and now they've asked to subscribe again, all // they've asked to subscribe again, all before the original subscription even
// before the original subscription even completed; we need do // completed; we need do nothing here except as the original subscription request will
// nothing here except as the original subscription request // eventually come through and all will be well
// will eventually come through and all will be well
return; return;
} }
// we're not pending and we just became active, that means we need // we're not pending and we just became active, that means we need to request to subscribe
// to request to subscribe to our object // to our object
_pending = true; _pending = true;
omgr.subscribeToObject(_oid, this); omgr.subscribeToObject(_oid, this);
} }
/** /**
* Terminates the object subscription. If the initial subscription has * Terminates the object subscription. If the initial subscription has not yet completed, the
* not yet completed, the desire to terminate will be noted and the * desire to terminate will be noted and the subscription will be terminated as soon as it
* subscription will be terminated as soon as it completes. * completes.
*/ */
public function unsubscribe (omgr :DObjectManager) :void public function unsubscribe (omgr :DObjectManager) :void
{ {
if (!_active) { if (!_active) {
// we may be non-active and have no object which could mean // we may be non-active and have no object which could mean that subscription failed;
// that subscription failed; in which case we don't want to // in which case we don't want to complain about anything, just quietly ignore the
// complain about anything, just quietly ignore the
// unsubscribe request // unsubscribe request
if (_object == null && !_pending) { if (_object == null && !_pending) {
return; return;
} }
log.warning("Inactive safesub asked to unsubscribe " + this + "."); log.warning("Inactive safesub asked to unsubscribe " + this);
Log.dumpStack(); Log.dumpStack();
} }
@@ -129,21 +121,17 @@ public class SafeSubscriber implements Subscriber
if (_pending) { if (_pending) {
// make sure we don't have an object reference // make sure we don't have an object reference
if (_object != null) { if (_object != null) {
log.warning("Incroyable! A safesub has an object and is " + log.warning("Have an object and am pending!? " + this, new Error());
"pending!? " + this + ".");
Log.dumpStack();
} else { } else {
// nothing to do but wait for the subscription to complete // nothing to do but wait for the subscription to complete at which point we'll
// at which point we'll pitch the object post-haste // pitch the object post-haste
return; return;
} }
} }
// make sure we have our object // make sure we have our object
if (_object == null) { if (_object == null) {
log.warning("Zut alors! A safesub _was_ active and not " + log.warning("Was active and not pending yet have no object!? " + this, new Error());
"pending yet has no object!? " + this + ".");
Log.dumpStack();
// nothing to do since we're apparently already unsubscribed // nothing to do since we're apparently already unsubscribed
return; return;
} }
@@ -158,14 +146,12 @@ public class SafeSubscriber implements Subscriber
{ {
// make sure life is not too cruel // make sure life is not too cruel
if (_object != null) { if (_object != null) {
log.warning("Madre de dios! Our object came available but " + log.warning("Our object came available but we've already got one!? " + this);
"we've already got one!? " + this);
// go ahead and pitch the old one, God knows what's going on // go ahead and pitch the old one, God knows what's going on
_object = null; _object = null;
} }
if (!_pending) { if (!_pending) {
log.warning("J.C. on a pogo stick! Our object came available " + log.warning("Our object came available but we're not pending!? " + this);
"but we're not pending!? " + this);
// go with our badselves, it's the only way // go with our badselves, it's the only way
} }
@@ -175,9 +161,8 @@ public class SafeSubscriber implements Subscriber
// if we are no longer active, we don't want this damned thing // if we are no longer active, we don't want this damned thing
if (!_active) { if (!_active) {
var omgr :DObjectManager = object.getManager(); var omgr :DObjectManager = object.getManager();
// if the object's manager is null, that means the object is // if the object's manager is null, that means the object is already destroyed and we
// already destroyed and we need not trouble ourselves with // need not trouble ourselves with unsubscription as it has already been pitched
// unsubscription as it has already been pitched to the dogs
if (omgr != null) { if (omgr != null) {
omgr.unsubscribeFromObject(_oid, this); omgr.unsubscribeFromObject(_oid, this);
} }
@@ -194,16 +179,15 @@ public class SafeSubscriber implements Subscriber
{ {
// do the right thing with our pending state // do the right thing with our pending state
if (!_pending) { if (!_pending) {
log.warning("Criminy creole! Our subscribe failed but we're " + log.warning("Criminy creole! Our subscribe failed but we're not pending!? " + this);
"not pending!? " + this);
// go with our badselves, it's the only way // go with our badselves, it's the only way
} }
_pending = false; _pending = false;
// if we're active, let our subscriber know that the shit hit the fan // if we're active, let our subscriber know that the shit hit the fan
if (_active) { if (_active) {
// deactivate ourselves as we never got our object (and thus // deactivate ourselves as we never got our object (and thus the real subscriber need
// the real subscriber need not call unsubscribe()) // not call unsubscribe())
_active = false; _active = false;
_subscriber.requestFailed(oid, cause); _subscriber.requestFailed(oid, cause);
} }
@@ -222,5 +206,7 @@ public class SafeSubscriber implements Subscriber
protected var _object :DObject;; protected var _object :DObject;;
protected var _active :Boolean; protected var _active :Boolean;
protected var _pending :Boolean; protected var _pending :Boolean;
private static const log :Log = Log.getLog(SafeSubscriber);
} }
} }