The great Interval revamp.

There is no more SafeInterval, instead Intervals can be constructed with a RunQueue to use for expiring.
PresentsDObjectMgr implements RunQueue.
Client has a getRunQueue() method to get the client side RunQueue.


git-svn-id: svn+ssh://src.earth.threerings.net/narya/trunk@3283 542714f4-19e9-0310-aa3c-eee0fc999fb1
This commit is contained in:
Ray Greenwell
2004-12-22 19:23:00 +00:00
parent 8ee6cb6fae
commit bd80c348eb
22 changed files with 199 additions and 391 deletions
@@ -22,9 +22,9 @@
package com.threerings.presents.client;
import com.samskivert.util.Interval;
import com.samskivert.util.IntervalManager;
import com.samskivert.util.ObserverList;
import com.samskivert.util.RunAnywhere;
import com.samskivert.util.RunQueue;
import com.threerings.presents.Log;
import com.threerings.presents.data.ClientObject;
@@ -46,42 +46,28 @@ public class Client
* connections. */
public static final int DEFAULT_SERVER_PORT = 4007;
/**
* This is used by the client to allow dobj event dispatching to take
* place along side the activities of the rest of the application
* (usually this means running dobj events on the AWT thread).
*/
public static interface Invoker
{
/**
* Requests that the supplied runnable be queued up for invocation
* on the main event dispatching thread of the application.
*/
public void invokeLater (Runnable run);
}
/**
* Constructs a client object with the supplied credentials and
* invoker. The creds will be used to authenticate with any server to
* which this client attempts to connect. The invoker is used to
* RunQueue. The creds will be used to authenticate with any server to
* which this client attempts to connect. The RunQueue is used to
* operate the distributed object event dispatch mechanism. To allow
* the dobj event dispatch to coexist with threads like the AWT
* thread, the client will request that the invoker queue up a
* thread, the client will request that the RunQueue queue up a
* runnable whenever there are distributed object events that need to
* be processed. The invoker can then queue that runnable up on the
* be processed. The RunQueue can then queue that runnable up on the
* AWT thread if it is so inclined to make life simpler for the rest
* of the application.
*
* @param creds the credentials to use when logging on to the server.
* These can be null, but <code>setCredentials</code> must then be
* called before any call to <code>logon</code>.
* @param invoker an invoker that can be used to process incoming
* @param runQueue a RunQueue that can be used to process incoming
* events.
*/
public Client (Credentials creds, Invoker invoker)
public Client (Credentials creds, RunQueue runQueue)
{
_creds = creds;
_invoker = invoker;
_runQueue = runQueue;
}
/**
@@ -125,12 +111,12 @@ public class Client
}
/**
* Returns the invoker in use by this client. This can be used to
* Returns the RunQueue in use by this client. This can be used to
* queue up event dispatching stints.
*/
public Invoker getInvoker ()
public RunQueue getRunQueue ()
{
return _invoker;
return _runQueue;
}
/**
@@ -369,15 +355,12 @@ public class Client
// register an interval that we'll use to keep the clock synced
// and to send pings when appropriate
_piid = IntervalManager.register(new Interval() {
public void intervalExpired (int id, Object arg) {
if (id != _piid) {
IntervalManager.remove(id);
} else {
tick();
}
_tickInterval = new Interval() {
public void expired () {
tick();
}
}, 5000L, null, true);
};
_tickInterval.schedule(5000L, true);
}
/**
@@ -408,7 +391,8 @@ public class Client
}
// kill our tick interval
_piid = -1;
_tickInterval.cancel();
_tickInterval = null;
// ask the communicator to send a logoff message and disconnect
// from the server
@@ -517,17 +501,17 @@ public class Client
};
// we need to run immediately if this is WILL_LOGOFF or if we have
// no invoker (which currently only happens in some really obscure
// no RunQueue (which currently only happens in some really obscure
// circumstances where we're using a Client instance on the server
// so that we can sort of pretend to be a real client)
if (code == CLIENT_WILL_LOGOFF || _invoker == null) {
if (code == CLIENT_WILL_LOGOFF || _runQueue == null) {
unit.run();
return noty.getRejected();
} else {
// otherwise we can queue this notification up with our
// invoker and ensure that it's run on the proper thread
_invoker.invokeLater(unit);
// RunQueue and ensure that it's run on the proper thread
_runQueue.postRunnable(unit);
return false;
}
}
@@ -537,10 +521,10 @@ public class Client
// we know that prior to the call to this method, the observers
// were notified with CLIENT_DID_LOGOFF; that may not have been
// invoked yet, so we don't want to clear out our communicator
// reference immediately; instead we queue up an invoker unit to
// reference immediately; instead we queue up a runnable unit to
// do so to ensure that it won't happen until CLIENT_DID_LOGOFF
// was dispatched
_invoker.invokeLater(new Runnable() {
_runQueue.postRunnable(new Runnable() {
public void run () {
// clear out our references
_comm = null;
@@ -677,7 +661,7 @@ public class Client
/** An entity that gives us the ability to process events on the main
* client thread (which is also the AWT thread). */
protected Invoker _invoker;
protected RunQueue _runQueue;
/** The data associated with our authentication response. */
protected AuthResponseData _authData;
@@ -723,7 +707,7 @@ public class Client
protected long _lastSync;
/** Our tick interval id. */
protected int _piid = -1;
protected Interval _tickInterval;
/** How often we recompute our time offset from the server. */
protected static final long CLOCK_SYNC_INTERVAL = 600 * 1000L;
@@ -1,5 +1,5 @@
//
// $Id: ClientDObjectMgr.java,v 1.26 2004/08/27 02:20:17 mdb Exp $
// $Id$
//
// Narya library - tools for developing networked games
// Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved
@@ -32,10 +32,9 @@ import com.samskivert.util.DebugChords;
import com.samskivert.util.HashIntMap;
import com.samskivert.util.Queue;
import com.samskivert.util.StringUtil;
import com.samskivert.util.IntervalManager;
import com.samskivert.util.Interval;
import com.threerings.presents.Log;
import com.threerings.presents.client.util.SafeInterval;
import com.threerings.presents.dobj.*;
import com.threerings.presents.net.*;
@@ -68,11 +67,11 @@ public class ClientDObjectMgr
DUMP_OTABLE_MODMASK, DUMP_OTABLE_KEYCODE, DUMP_OTABLE_HOOK);
// register a flush interval
IntervalManager.register(new SafeInterval(client) {
public void run () {
new Interval(client.getRunQueue()) {
public void expired () {
flushObjects();
}
}, FLUSH_INTERVAL, null, true);
}.schedule(FLUSH_INTERVAL, true);
}
// documentation inherited from interface
@@ -111,7 +110,7 @@ public class ClientDObjectMgr
// queue up an action
_actions.append(new ObjectAction(oid, target, subscribe));
// and queue up the omgr to get invoked on the invoker thread
_client.getInvoker().invokeLater(this);
_client.getRunQueue().postRunnable(this);
}
// inherit documentation from the interface
@@ -170,7 +169,7 @@ public class ClientDObjectMgr
// append it to our queue
_actions.append(msg);
// and queue ourselves up to be run
_client.getInvoker().invokeLater(this);
_client.getRunQueue().postRunnable(this);
}
/**
@@ -1,76 +0,0 @@
//
// $Id: SafeInterval.java,v 1.4 2004/08/27 02:20:18 mdb Exp $
//
// Narya library - tools for developing networked games
// Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved
// http://www.threerings.net/code/narya/
//
// This library is free software; you can redistribute it and/or modify it
// under the terms of the GNU Lesser General Public License as published
// by the Free Software Foundation; either version 2.1 of the License, or
// (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
package com.threerings.presents.client.util;
import com.samskivert.util.Interval;
import com.threerings.presents.client.Client;
/**
* Used in conjunction with the {@link Client}, this class provides a
* means by which code can be run on the client main thread at some point
* in the future, either as a recurring interval or as a one shot deal.
* The code is built on top of the {@link IntervalManager} services.
*
* <p> A {@link SafeInterval} instance should be created and then
* scheduled to run using the {@link IntervalManager}. For example:
*
* <pre>
* IntervalManager.register(new SafeInterval(_ctx.getClient()) {
* public void run () {
* System.out.println("Foo!");
* }
* }, 25L * 1000L, null, false);
* </pre>
*/
public abstract class SafeInterval
implements Runnable, Interval
{
/**
* Creates a safe interval instance that will queue itself up for
* execution using the supplied client when it expires.
*/
public SafeInterval (Client client)
{
_client = client;
}
/**
* Called (on the client main thread) when the interval period has
* expired. If this is a recurring interval, this method will be
* called each time the interval expires.
*/
public abstract void run ();
/** Handles the proper scheduling and queueing. */
public void intervalExpired (int id, Object arg)
{
_iid = id;
_client.getInvoker().invokeLater(this);
}
/** The client via which we queue ourselves when we expire. */
protected Client _client;
/** Configured with our current interval id when we are triggered. */
protected int _iid;
}