From bd80c348ebb33534d49c6bc242ff7818450671b4 Mon Sep 17 00:00:00 2001 From: Ray Greenwell Date: Wed, 22 Dec 2004 19:23:00 +0000 Subject: [PATCH] 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 --- .../threerings/crowd/server/PlaceManager.java | 35 +++----- .../threerings/media/sound/SoundManager.java | 18 ++--- .../micasa/client/MiCasaClient.java | 19 +++-- .../micasa/simulator/client/SimpleClient.java | 19 +++-- .../micasa/simulator/client/SimulatorApp.java | 9 +-- .../threerings/parlor/game/AIGameTicker.java | 16 ++-- .../parlor/game/GameController.java | 2 +- .../threerings/parlor/game/GameManager.java | 33 ++++---- .../threerings/presents/client/Client.java | 68 ++++++---------- .../presents/client/ClientDObjectMgr.java | 15 ++-- .../presents/client/util/SafeInterval.java | 76 ----------------- .../presents/server/ClientManager.java | 9 +-- .../presents/server/PresentsClient.java | 4 +- .../presents/server/PresentsDObjectMgr.java | 17 ++-- .../presents/server/PresentsInvoker.java | 4 +- .../presents/server/PresentsServer.java | 22 ++--- .../presents/server/util/SafeInterval.java | 76 ----------------- .../puzzle/client/PuzzleBoardView.java | 2 +- .../puzzle/server/PuzzleManager.java | 33 ++++---- .../com/threerings/util/KeyboardManager.java | 81 +++++++------------ src/java/com/threerings/util/RobotPlayer.java | 28 +++---- .../whirled/server/SceneManager.java | 4 +- 22 files changed, 199 insertions(+), 391 deletions(-) delete mode 100644 src/java/com/threerings/presents/client/util/SafeInterval.java delete mode 100644 src/java/com/threerings/presents/server/util/SafeInterval.java diff --git a/src/java/com/threerings/crowd/server/PlaceManager.java b/src/java/com/threerings/crowd/server/PlaceManager.java index e13516bc6..df24f2625 100644 --- a/src/java/com/threerings/crowd/server/PlaceManager.java +++ b/src/java/com/threerings/crowd/server/PlaceManager.java @@ -1,5 +1,5 @@ // -// $Id: PlaceManager.java,v 1.51 2004/08/27 02:12:34 mdb Exp $ +// $Id$ // // Narya library - tools for developing networked games // Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved @@ -26,13 +26,12 @@ import java.util.HashMap; import java.util.Iterator; import com.samskivert.util.HashIntMap; -import com.samskivert.util.IntervalManager; +import com.samskivert.util.Interval; import com.samskivert.util.StringUtil; import com.threerings.presents.data.ClientObject; import com.threerings.presents.server.InvocationManager; import com.threerings.presents.server.PresentsDObjectMgr; -import com.threerings.presents.server.util.SafeInterval; import com.threerings.presents.dobj.DObject; import com.threerings.presents.dobj.DObjectManager; @@ -468,21 +467,13 @@ public class PlaceManager // queue up a shutdown interval long idlePeriod = idleUnloadPeriod(); if (idlePeriod > 0L) { - SafeInterval si = new SafeInterval((PresentsDObjectMgr)_omgr) { - public void intervalExpired (int id, Object arg) { - _iid = id; - super.intervalExpired(id, arg); + _shutdownInterval = new Interval((PresentsDObjectMgr)_omgr) { + public void expired () { + Log.debug("Unloading idle place '" + where () + "'."); + shutdown(); } - public void run () { - if (_iid == _shutdownId) { - _shutdownId = -1; - Log.debug("Unloading idle place '" + where () + "'."); - shutdown(); - } - } - protected int _iid; }; - _shutdownId = IntervalManager.register(si, idlePeriod, null, false); + _shutdownInterval.schedule(idlePeriod); } } @@ -491,9 +482,9 @@ public class PlaceManager */ protected void cancelShutdowner () { - if (_shutdownId != -1) { - IntervalManager.remove(_shutdownId); - _shutdownId = -1; + if (_shutdownInterval != null) { + _shutdownInterval.cancel(); + _shutdownInterval = null; } } @@ -690,8 +681,8 @@ public class PlaceManager /** Used to keep a canonical copy of the occupant info records. */ protected HashIntMap _occInfo = new HashIntMap(); - /** The id of the interval currently registered to shut this place - * down after a certain period of idility. Is -1 if no + /** The interval currently registered to shut this place + * down after a certain period of idility, or null if no * interval is currently registered. */ - protected int _shutdownId = -1; + protected Interval _shutdownInterval; } diff --git a/src/java/com/threerings/media/sound/SoundManager.java b/src/java/com/threerings/media/sound/SoundManager.java index c2730c9c5..aa718ee0f 100644 --- a/src/java/com/threerings/media/sound/SoundManager.java +++ b/src/java/com/threerings/media/sound/SoundManager.java @@ -1,5 +1,5 @@ // -// $Id: SoundManager.java,v 1.74 2004/08/27 02:12:40 mdb Exp $ +// $Id$ // // Narya library - tools for developing networked games // Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved @@ -49,7 +49,6 @@ import org.apache.commons.io.IOUtils; import com.samskivert.util.Config; import com.samskivert.util.Interval; -import com.samskivert.util.IntervalManager; import com.samskivert.util.LRUHashMap; import com.samskivert.util.Queue; import com.samskivert.util.RuntimeAdjust; @@ -375,9 +374,13 @@ public class SoundManager } if (_player != null && (_clipVol != 0f) && isEnabled(type)) { - SoundKey skey = new SoundKey(pkgPath, key, delay); + final SoundKey skey = new SoundKey(pkgPath, key, delay); if (delay > 0) { - IntervalManager.register(_playLater, delay, skey, false); + new Interval() { + public void expired () { + addToPlayQueue(skey); + } + }.schedule(delay); } else { addToPlayQueue(skey); } @@ -1254,13 +1257,6 @@ public class SoundManager /** If we every play a sound successfully, this is set to true. */ protected boolean _soundSeemsToWork = false; - /** An interval that plays sounds later. */ - protected Interval _playLater = new Interval() { - public void intervalExpired (int id, Object rock) { - addToPlayQueue((SoundKey) rock); - } - }; - /** Volume levels for both sound clips and music. */ protected float _clipVol = 1f, _musicVol = 1f; diff --git a/src/java/com/threerings/micasa/client/MiCasaClient.java b/src/java/com/threerings/micasa/client/MiCasaClient.java index e14950d55..126c60b69 100644 --- a/src/java/com/threerings/micasa/client/MiCasaClient.java +++ b/src/java/com/threerings/micasa/client/MiCasaClient.java @@ -21,13 +21,14 @@ package com.threerings.micasa.client; +import java.awt.EventQueue; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.io.IOException; import javax.swing.JPanel; -import javax.swing.SwingUtilities; import com.samskivert.util.Config; +import com.samskivert.util.RunQueue; import com.threerings.util.MessageManager; import com.threerings.presents.client.Client; @@ -50,7 +51,7 @@ import com.threerings.micasa.util.MiCasaContext; * extended context implementation. */ public class MiCasaClient - implements Client.Invoker + implements RunQueue { /** * Initializes a new client and provides it with a frame in which to @@ -128,11 +129,17 @@ public class MiCasaClient _chatdir = new ChatDirector(_ctx, _msgmgr, null); } - // documentation inherited - public void invokeLater (Runnable run) + // documentation inherited from interface RunQueue + public void postRunnable (Runnable run) { - // queue it on up on the swing thread - SwingUtilities.invokeLater(run); + // queue it on up on the awt thread + EventQueue.invokeLater(run); + } + + // documentation inherited from interface RunQueue + public boolean isDispatchThread () + { + return EventQueue.isDispatchThread(); } /** diff --git a/src/java/com/threerings/micasa/simulator/client/SimpleClient.java b/src/java/com/threerings/micasa/simulator/client/SimpleClient.java index a3161a823..66a0e9316 100644 --- a/src/java/com/threerings/micasa/simulator/client/SimpleClient.java +++ b/src/java/com/threerings/micasa/simulator/client/SimpleClient.java @@ -21,15 +21,16 @@ package com.threerings.micasa.simulator.client; +import java.awt.EventQueue; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.io.IOException; import javax.swing.JPanel; -import javax.swing.SwingUtilities; import com.samskivert.util.Config; +import com.samskivert.util.RunQueue; import com.threerings.util.MessageManager; import com.threerings.presents.client.Client; @@ -48,7 +49,7 @@ import com.threerings.micasa.client.MiCasaFrame; import com.threerings.micasa.util.MiCasaContext; public class SimpleClient - implements Client.Invoker, SimulatorClient + implements RunQueue, SimulatorClient { public SimpleClient (SimulatorFrame frame) throws IOException @@ -106,11 +107,17 @@ public class SimpleClient return _ctx; } - // documentation inherited - public void invokeLater (Runnable run) + // documentation inherited from interface RunQueue + public void postRunnable (Runnable run) { - // queue it on up on the swing thread - SwingUtilities.invokeLater(run); + // queue it on up on the awt thread + EventQueue.invokeLater(run); + } + + // documentation inherited from interface RunQueue + public boolean isDispatchThread () + { + return EventQueue.isDispatchThread(); } /** diff --git a/src/java/com/threerings/micasa/simulator/client/SimulatorApp.java b/src/java/com/threerings/micasa/simulator/client/SimulatorApp.java index 836dba1c8..eb2989de0 100644 --- a/src/java/com/threerings/micasa/simulator/client/SimulatorApp.java +++ b/src/java/com/threerings/micasa/simulator/client/SimulatorApp.java @@ -1,5 +1,5 @@ // -// $Id: SimulatorApp.java,v 1.17 2004/08/27 02:12:52 mdb Exp $ +// $Id$ // // Narya library - tools for developing networked games // Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved @@ -26,7 +26,6 @@ import javax.swing.JFrame; import com.samskivert.swing.Controller; import com.samskivert.swing.util.SwingUtil; import com.samskivert.util.Interval; -import com.samskivert.util.IntervalManager; import com.samskivert.util.ResultListener; import com.threerings.util.Name; @@ -167,11 +166,11 @@ public class SimulatorApp // wholly independent thread to wait for the server to be ready as // in normal circumstances they are entirely different processes; // so we just wait half a second which does the job - IntervalManager.register(new Interval() { - public void intervalExpired (int id, Object arg) { + new Interval() { + public void expired () { _client.getParlorContext().getClient().logon(); } - }, 500L, null, false); + }.schedule(500L); } public static void main (String[] args) diff --git a/src/java/com/threerings/parlor/game/AIGameTicker.java b/src/java/com/threerings/parlor/game/AIGameTicker.java index 604105f0c..5e3150028 100644 --- a/src/java/com/threerings/parlor/game/AIGameTicker.java +++ b/src/java/com/threerings/parlor/game/AIGameTicker.java @@ -1,5 +1,5 @@ // -// $Id: AIGameTicker.java,v 1.6 2004/08/27 02:20:14 mdb Exp $ +// $Id$ // // Narya library - tools for developing networked games // Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved @@ -24,15 +24,14 @@ package com.threerings.parlor.game; import java.util.Iterator; import java.util.HashSet; -import com.samskivert.util.IntervalManager; +import com.samskivert.util.Interval; -import com.threerings.presents.server.util.SafeInterval; import com.threerings.crowd.server.CrowdServer; /** * Handles ticking all the GameManagers that are hosting games with AIs. */ -public class AIGameTicker extends SafeInterval +public class AIGameTicker extends Interval { /** The frequency with which we dispatch AI game ticks. */ public static final long TICK_FREQUENCY = 3333L; // every 3 1/3 seconds @@ -66,7 +65,7 @@ public class AIGameTicker extends SafeInterval super(CrowdServer.omgr); _games = new HashSet(); - _id = IntervalManager.register(this, TICK_FREQUENCY, null, true); + schedule(TICK_FREQUENCY, true); } /** @@ -88,15 +87,15 @@ public class AIGameTicker extends SafeInterval // if there aren't any AIs, let's stop running if (_games.isEmpty()) { + cancel(); _ticker = null; - IntervalManager.remove(_id); } } /** * Tick all the game AIs while on the dobj thread. */ - public void run () + public void expired () { Iterator iter = _games.iterator(); while (iter.hasNext()) { @@ -107,9 +106,6 @@ public class AIGameTicker extends SafeInterval /** Our set of ai games. */ protected HashSet _games; - /** Our interval id. */ - protected int _id; - /** Our single ticker for all AI games. */ protected static AIGameTicker _ticker; } diff --git a/src/java/com/threerings/parlor/game/GameController.java b/src/java/com/threerings/parlor/game/GameController.java index 3449017b0..26136ffdc 100644 --- a/src/java/com/threerings/parlor/game/GameController.java +++ b/src/java/com/threerings/parlor/game/GameController.java @@ -99,7 +99,7 @@ public abstract class GameController extends PlaceController Name username = ((BodyObject)_ctx.getClient().getClientObject()).username; if (_gobj.getPlayerIndex(username) != -1) { - _ctx.getClient().getInvoker().invokeLater(new Runnable() { + _ctx.getClient().getRunQueue().postRunnable(new Runnable() { public void run () { // finally let the game manager know that we're ready // to roll diff --git a/src/java/com/threerings/parlor/game/GameManager.java b/src/java/com/threerings/parlor/game/GameManager.java index db7153980..9f5c2bb23 100644 --- a/src/java/com/threerings/parlor/game/GameManager.java +++ b/src/java/com/threerings/parlor/game/GameManager.java @@ -25,7 +25,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Iterator; -import com.samskivert.util.IntervalManager; +import com.samskivert.util.Interval; import com.samskivert.util.RepeatCallTracker; import com.samskivert.util.StringUtil; import com.threerings.util.Name; @@ -35,7 +35,6 @@ import com.threerings.presents.dobj.AttributeChangeListener; import com.threerings.presents.dobj.AttributeChangedEvent; import com.threerings.presents.dobj.DObject; import com.threerings.presents.dobj.OidList; -import com.threerings.presents.server.util.SafeInterval; import com.threerings.crowd.chat.server.SpeakProvider; @@ -72,13 +71,13 @@ public class GameManager extends PlaceManager _managers.add(this); // and start up a tick interval if we've not already got one - if (_tiid == -1) { - _tiid = IntervalManager.register( - new SafeInterval(CrowdServer.omgr) { - public void run () { - tickAllGames(); - } - }, TICK_DELAY, null, true); + if (_tickInterval == null) { + _tickInterval = new Interval(CrowdServer.omgr) { + public void expired () { + tickAllGames(); + } + }; + _tickInterval.schedule(TICK_DELAY, true); } } @@ -443,11 +442,11 @@ public class GameManager extends PlaceManager // start up a no-show timer if needed if (needsNoShowTimer()) { - IntervalManager.register(new SafeInterval(CrowdServer.omgr) { - public void run () { + new Interval(CrowdServer.omgr) { + public void expired () { checkForNoShows(); } - }, NOSHOW_DELAY, null, false); + }.schedule(NOSHOW_DELAY); } } @@ -471,8 +470,8 @@ public class GameManager extends PlaceManager // remove the tick interval if there are no remaining managers if (_managers.size() == 0) { - IntervalManager.remove(_tiid); - _tiid = -1; + _tickInterval.cancel(); + _tickInterval = null; } // clear out our service registration @@ -610,7 +609,7 @@ public class GameManager extends PlaceManager if (_committedState == GameObject.IN_PLAY) { Log.info("Postponing start of still-ending game " + "[which=" + _gameobj.which() + "]."); - CrowdServer.omgr.postUnit(new Runnable() { + CrowdServer.omgr.postRunnable(new Runnable() { public void run () { startGame(); } @@ -1087,8 +1086,8 @@ public class GameManager extends PlaceManager /** A list of all currently active game managers. */ protected static ArrayList _managers = new ArrayList(); - /** The interval id for the game manager tick interval. */ - protected static int _tiid = -1; + /** The interval for the game manager tick. */ + protected static Interval _tickInterval; /** We give players 30 seconds to turn up in a puzzle and after that, * they're considered a no show. */ diff --git a/src/java/com/threerings/presents/client/Client.java b/src/java/com/threerings/presents/client/Client.java index ab876ecc5..52910f17e 100644 --- a/src/java/com/threerings/presents/client/Client.java +++ b/src/java/com/threerings/presents/client/Client.java @@ -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 setCredentials must then be * called before any call to logon. - * @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; diff --git a/src/java/com/threerings/presents/client/ClientDObjectMgr.java b/src/java/com/threerings/presents/client/ClientDObjectMgr.java index 7200be4f6..a5322a5f6 100644 --- a/src/java/com/threerings/presents/client/ClientDObjectMgr.java +++ b/src/java/com/threerings/presents/client/ClientDObjectMgr.java @@ -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); } /** diff --git a/src/java/com/threerings/presents/client/util/SafeInterval.java b/src/java/com/threerings/presents/client/util/SafeInterval.java deleted file mode 100644 index 973b3b9cc..000000000 --- a/src/java/com/threerings/presents/client/util/SafeInterval.java +++ /dev/null @@ -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. - * - *

A {@link SafeInterval} instance should be created and then - * scheduled to run using the {@link IntervalManager}. For example: - * - *

- *     IntervalManager.register(new SafeInterval(_ctx.getClient()) {
- *         public void run () {
- *             System.out.println("Foo!");
- *         }
- *      }, 25L * 1000L, null, false);
- * 
- */ -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; -} diff --git a/src/java/com/threerings/presents/server/ClientManager.java b/src/java/com/threerings/presents/server/ClientManager.java index cc22ef788..16bed512f 100644 --- a/src/java/com/threerings/presents/server/ClientManager.java +++ b/src/java/com/threerings/presents/server/ClientManager.java @@ -27,7 +27,7 @@ import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; -import com.samskivert.util.IntervalManager; +import com.samskivert.util.Interval; import com.samskivert.util.StringUtil; import com.threerings.util.Name; @@ -38,7 +38,6 @@ import com.threerings.presents.net.AuthRequest; import com.threerings.presents.net.AuthResponse; import com.threerings.presents.net.Credentials; import com.threerings.presents.server.net.*; -import com.threerings.presents.server.util.SafeInterval; /** * The client manager is responsible for managing the clients (surprise, @@ -82,11 +81,11 @@ public class ClientManager // start up an interval that will check for expired clients and // flush them from the bowels of the server - IntervalManager.register(new SafeInterval(PresentsServer.omgr) { - public void run () { + new Interval(PresentsServer.omgr) { + public void expired () { flushClients(); } - }, CLIENT_FLUSH_INTERVAL, null, true); + }.schedule(CLIENT_FLUSH_INTERVAL, true); // register as a "state of server" reporter and a shutdowner PresentsServer.registerReporter(this); diff --git a/src/java/com/threerings/presents/server/PresentsClient.java b/src/java/com/threerings/presents/server/PresentsClient.java index 19ca67e40..076f9744a 100644 --- a/src/java/com/threerings/presents/server/PresentsClient.java +++ b/src/java/com/threerings/presents/server/PresentsClient.java @@ -438,7 +438,7 @@ public class PresentsClient */ protected void safeEndSession () { - PresentsServer.omgr.postUnit(new Runnable() { + PresentsServer.omgr.postRunnable(new Runnable() { public void run () { if (getClientObject() == null) { // refuse to end the session unless the client is @@ -624,7 +624,7 @@ public class PresentsClient // our connection reference. once the connection ref is null, no // more subscriptions will be processed (even those that were // queued up before the connection went away) - PresentsServer.omgr.postUnit(new Runnable() { + PresentsServer.omgr.postRunnable(new Runnable() { public void run () { sessionConnectionClosed(); } diff --git a/src/java/com/threerings/presents/server/PresentsDObjectMgr.java b/src/java/com/threerings/presents/server/PresentsDObjectMgr.java index 0dca3be83..3034a9108 100644 --- a/src/java/com/threerings/presents/server/PresentsDObjectMgr.java +++ b/src/java/com/threerings/presents/server/PresentsDObjectMgr.java @@ -1,5 +1,5 @@ // -// $Id: PresentsDObjectMgr.java,v 1.48 2004/10/28 21:59:00 mdb Exp $ +// $Id$ // // Narya library - tools for developing networked games // Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved @@ -30,8 +30,8 @@ import sun.misc.Perf; import com.samskivert.util.HashIntMap; import com.samskivert.util.Histogram; -import com.samskivert.util.Invoker; import com.samskivert.util.Queue; +import com.samskivert.util.RunQueue; import com.samskivert.util.StringUtil; import com.samskivert.util.Throttle; @@ -52,8 +52,7 @@ import com.threerings.presents.dobj.*; * requested to shut down. */ public class PresentsDObjectMgr - implements RootDObjectManager, Invoker.ResultReceiver, - PresentsServer.Reporter + implements RootDObjectManager, RunQueue, PresentsServer.Reporter { /** * Creates the dobjmgr and prepares it for operation. @@ -146,8 +145,10 @@ public class PresentsDObjectMgr * opportunity. The code will be queued up with the rest of the events * and invoked in turn. Like event processing code, the code should * not take long to complete and should definitely not block. + * + * From interface RunQueue */ - public void postUnit (Runnable unit) + public void postRunnable (Runnable unit) { // just append it to the queue _evqueue.append(unit); @@ -172,8 +173,10 @@ public class PresentsDObjectMgr * that is doing distributed object event dispatch. Code that wishes * to enforce that it is either always or never called on the event * dispatch thread will want to make use of this method. + * + * From interface RunQueue */ - public synchronized boolean isEventDispatchThread () + public synchronized boolean isDispatchThread () { return Thread.currentThread() == _dobjThread; } @@ -378,7 +381,7 @@ public class PresentsDObjectMgr */ public void harshShutdown () { - postUnit(new Runnable() { + postRunnable(new Runnable() { public void run () { _running = false; } diff --git a/src/java/com/threerings/presents/server/PresentsInvoker.java b/src/java/com/threerings/presents/server/PresentsInvoker.java index c07b38d5e..2784245ec 100644 --- a/src/java/com/threerings/presents/server/PresentsInvoker.java +++ b/src/java/com/threerings/presents/server/PresentsInvoker.java @@ -1,5 +1,5 @@ // -// $Id: PresentsInvoker.java,v 1.2 2004/08/27 02:20:23 mdb Exp $ +// $Id$ // // Narya library - tools for developing networked games // Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved @@ -110,7 +110,7 @@ public class PresentsInvoker extends Invoker // if the queue isn't empty, re-post } else if (!_omgr.queueIsEmpty()) { _loopCount++; - _omgr.postUnit(this); + _omgr.postRunnable(this); // if the invoker still has stuff and we're still under the pass // limit, go ahead and pass it back to the invoker diff --git a/src/java/com/threerings/presents/server/PresentsServer.java b/src/java/com/threerings/presents/server/PresentsServer.java index db2623ffc..f5aa34550 100644 --- a/src/java/com/threerings/presents/server/PresentsServer.java +++ b/src/java/com/threerings/presents/server/PresentsServer.java @@ -23,7 +23,7 @@ package com.threerings.presents.server; import java.util.ArrayList; -import com.samskivert.util.IntervalManager; +import com.samskivert.util.Interval; import com.samskivert.util.ObserverList; import com.samskivert.util.StringUtil; import com.samskivert.util.SystemInfo; @@ -33,7 +33,6 @@ import com.threerings.util.signal.SignalManager; import com.threerings.presents.Log; import com.threerings.presents.client.Client; import com.threerings.presents.server.net.ConnectionManager; -import com.threerings.presents.server.util.SafeInterval; /** * The presents server provides a central point of access to the various @@ -130,11 +129,11 @@ public class PresentsServer TimeBaseProvider.init(invmgr, omgr); // queue up an interval which will generate reports - IntervalManager.register(new SafeInterval(omgr) { - public void run () { + new Interval(omgr) { + public void expired () { generateReport(System.currentTimeMillis()); } - }, REPORT_INTERVAL, null, true); + }.schedule(REPORT_INTERVAL, true); } /** @@ -154,7 +153,7 @@ public class PresentsServer { // post a unit that will start up the connection manager when // everything else in the dobjmgr queue is processed - omgr.postUnit(new Runnable() { + omgr.postRunnable(new Runnable() { public void run () { // start up the connection manager conmgr.start(); @@ -215,12 +214,15 @@ public class PresentsServer } } - report.append("* samskivert.IntervalManager:\n"); + /* The following Interval debug methods are no longer supported, + * but they could be added back easily if needed. + report.append("* samskivert.Interval:\n"); report.append("- Registered intervals: "); - report.append(IntervalManager.registeredIntervalCount()); + report.append(Interval.registeredIntervalCount()); report.append("\n- Fired since last report: "); - report.append(IntervalManager.getAndClearFiredIntervals()); + report.append(Interval.getAndClearFiredIntervals()); report.append("\n"); + */ // strip off the final newline int blen = report.length(); @@ -277,7 +279,7 @@ public class PresentsServer */ public void queueShutdown () { - omgr.postUnit(new Runnable() { + omgr.postRunnable(new Runnable() { public void run () { shutdown(); } diff --git a/src/java/com/threerings/presents/server/util/SafeInterval.java b/src/java/com/threerings/presents/server/util/SafeInterval.java deleted file mode 100644 index 435b062ea..000000000 --- a/src/java/com/threerings/presents/server/util/SafeInterval.java +++ /dev/null @@ -1,76 +0,0 @@ -// -// $Id$ -// -// 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.server.util; - -import com.samskivert.util.Interval; - -import com.threerings.presents.server.PresentsDObjectMgr; - -/** - * Used in conjunction with the {@link PresentsDObjectMgr}, this class - * provides a means by which code can be run on the dobjmgr 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. - * - *

A {@link SafeInterval} instance should be created and then - * scheduled to run using the {@link IntervalManager}. For example: - * - *

- *     IntervalManager.register(new SafeInterval(_omgr) {
- *         public void run () {
- *             System.out.println("Foo!");
- *         }
- *      }, 25L * 1000L, null, false);
- * 
- */ -public abstract class SafeInterval - implements Runnable, Interval -{ - /** - * Creates a safe interval instance that will queue itself up for - * execution on the supplied dobjmgr when it expires. - */ - public SafeInterval (PresentsDObjectMgr omgr) - { - _omgr = omgr; - } - - /** - * Called (on the dobjmgr 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; - _omgr.postUnit(this); - } - - /** The dobjmgr on which we queue ourselves when we expire. */ - protected PresentsDObjectMgr _omgr; - - /** Configured with our current interval id when we are triggered. */ - protected int _iid; -} diff --git a/src/java/com/threerings/puzzle/client/PuzzleBoardView.java b/src/java/com/threerings/puzzle/client/PuzzleBoardView.java index bc13ca10b..5145d72d5 100644 --- a/src/java/com/threerings/puzzle/client/PuzzleBoardView.java +++ b/src/java/com/threerings/puzzle/client/PuzzleBoardView.java @@ -399,7 +399,7 @@ public abstract class PuzzleBoardView extends VirtualMediaPanel // animationDidFinish() call and we want everyone to finish // processing their business before we go clearing the action, // so we queue this up to be run after the tick is complete - _ctx.getClient().getInvoker().invokeLater(new Runnable() { + _ctx.getClient().getRunQueue().postRunnable(new Runnable() { public void run () { _pctrl.boardActionCleared(); } diff --git a/src/java/com/threerings/puzzle/server/PuzzleManager.java b/src/java/com/threerings/puzzle/server/PuzzleManager.java index 6edbb37cb..355cc1b75 100644 --- a/src/java/com/threerings/puzzle/server/PuzzleManager.java +++ b/src/java/com/threerings/puzzle/server/PuzzleManager.java @@ -24,13 +24,12 @@ package com.threerings.puzzle.server; import java.util.Arrays; import com.samskivert.util.IntListUtil; -import com.samskivert.util.IntervalManager; +import com.samskivert.util.Interval; import com.samskivert.util.StringUtil; import com.threerings.presents.data.ClientObject; import com.threerings.presents.dobj.DObject; import com.threerings.presents.dobj.OidList; -import com.threerings.presents.server.util.SafeInterval; import com.threerings.crowd.data.BodyObject; import com.threerings.crowd.server.CrowdServer; @@ -253,15 +252,15 @@ public abstract class PuzzleManager extends GameManager sendStatusUpdate(); long statusInterval = getStatusInterval(); - if (_uiid == -1 && statusInterval > 0) { + if (_statusInterval == null && statusInterval > 0) { // register the status update interval to address subsequent // periodic updates - _uiid = IntervalManager.register( - new SafeInterval(CrowdServer.omgr) { - public void run () { - sendStatusUpdate(); - } - }, statusInterval, null, true); + _statusInterval = new Interval(CrowdServer.omgr) { + public void expired () { + sendStatusUpdate(); + } + }; + _statusInterval.schedule(statusInterval, true); } } @@ -408,10 +407,10 @@ public abstract class PuzzleManager extends GameManager // documentation inherited protected void gameDidEnd () { - if (_uiid != -1) { + if (_statusInterval != null) { // remove the client update interval - IntervalManager.remove(_uiid); - _uiid = -1; + _statusInterval.cancel(); + _statusInterval = null; } // send along one final status update @@ -441,10 +440,10 @@ public abstract class PuzzleManager extends GameManager super.didShutdown(); // make sure our update interval is unregistered - if (_uiid != -1) { + if (_statusInterval != null) { // remove the client update interval - IntervalManager.remove(_uiid); - _uiid = -1; + _statusInterval.cancel(); + _statusInterval = null; } // clear out our service registration @@ -738,8 +737,8 @@ public abstract class PuzzleManager extends GameManager /** The player boards. */ protected Board[] _boards; - /** The client update interval identifier. */ - protected int _uiid = -1; + /** The client update interval. */ + protected Interval _statusInterval; /** Used to track the last time we received a progress event from each * player in this puzzle. */ diff --git a/src/java/com/threerings/util/KeyboardManager.java b/src/java/com/threerings/util/KeyboardManager.java index 2d84e9d75..6d8da4af9 100644 --- a/src/java/com/threerings/util/KeyboardManager.java +++ b/src/java/com/threerings/util/KeyboardManager.java @@ -1,5 +1,5 @@ // -// $Id: KeyboardManager.java,v 1.20 2004/08/27 02:20:36 mdb Exp $ +// $Id$ // // Narya library - tools for developing networked games // Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved @@ -39,7 +39,6 @@ import javax.swing.event.AncestorListener; import com.samskivert.swing.Controller; import com.samskivert.util.HashIntMap; import com.samskivert.util.Interval; -import com.samskivert.util.IntervalManager; import com.samskivert.util.ObserverList; import com.samskivert.util.RunAnywhere; @@ -405,7 +404,7 @@ public class KeyboardManager lostFocus(); } - protected class KeyInfo implements Interval + protected class KeyInfo extends Interval { /** * Constructs a key info object for the given key code. @@ -431,17 +430,16 @@ public class KeyboardManager postPress(time); } - if (_iid == -1 && _pressDelay > 0) { + if (!_scheduled && _pressDelay > 0) { // register an interval to post the key press command // until the key is decidedly released if (_repeatDelay > 0) { - _iid = IntervalManager.register( - this, _repeatDelay, this, false); + schedule(_repeatDelay, _pressDelay); } else { - _iid = IntervalManager.register( - this, _pressDelay, null, true); + schedule(_pressDelay, true); } + _scheduled = true; if (DEBUG_EVENTS) { Log.info("Pressing key [key=" + _keyText + "]."); @@ -503,15 +501,9 @@ public class KeyboardManager } // remove the repeat interval - if (_iid != -1) { - IntervalManager.remove(_iid); - _iid = -1; - } - - if (_siid != -1) { - // remove the sub-interval - IntervalManager.remove(_siid); - _siid = -1; + if (_scheduled) { + cancel(); + _scheduled = false; } if (_releaseCommand != null) { @@ -524,25 +516,24 @@ public class KeyboardManager } // documentation inherited - public synchronized void intervalExpired (int id, Object arg) + public synchronized void expired () { long now = System.currentTimeMillis(); long deltaPress = now - _lastPress; long deltaRelease = now - _lastRelease; if (KeyboardManager.DEBUG_INTERVAL) { - Log.info("Interval [id=" + id + ", key=" + _keyText + + Log.info("Interval [key=" + _keyText + ", deltaPress=" + deltaPress + ", deltaRelease=" + deltaRelease + "]."); } - if (id == _iid) { - // handle a normal interval where we either (a) create a - // sub-interval if we can't yet determine definitively - // whether the key is still down, (b) cease repeating if - // we're certain the key is now up, or (c) repeat the key - // command if we're certain the key is still down - if (_lastRelease != _lastPress) { + // handle a normal interval where we either (a) create a + // sub-interval if we can't yet determine definitively + // whether the key is still down, (b) cease repeating if + // we're certain the key is now up, or (c) repeat the key + // command if we're certain the key is still down + if (_lastRelease != _lastPress) { // if (deltaRelease < _repeatDelay) { // // register a one-shot sub-interval to // // definitively check whether the key was released @@ -555,25 +546,20 @@ public class KeyboardManager // } // } else { - // we know the key was released, so cease repeating - release(now); + // we know the key was released, so cease repeating + release(now); // } - } else if (_lastPress != 0 && _pressCommand != null) { - // post the key press command again - postPress(now); - - if (arg == this) { - // this key had a specific repeat delay interval - // that may differ from the once-started repeat - // rate, and so we need to re-register the - // interval to make use of the proper time and to - // continue repeating henceforth - _iid = IntervalManager.register( - this, _pressDelay, null, true); - } - } + } else if (_lastPress != 0 && _pressCommand != null) { + // post the key press command again + postPress(now); + } + } +/* + * Old stuff- sub interval stuff was commented out prior to my + * reworking of Interval, I'll be damned if I'm going to convert this + * code that wasn't even being used. } else if (id == _siid) { // handle the sub-interval that checks whether the key has // really been released since the normal interval expired @@ -604,6 +590,7 @@ public class KeyboardManager } } } + **/ /** * Posts the press command for this key and notifies all key @@ -631,14 +618,8 @@ public class KeyboardManager return "[key=" + _keyText + "]"; } - /** The unique interval identifier for the sub-interval used to - * handle the case where the main interval wakes up to repeat the - * currently pressed key and the last key release event was - * received more recently than the expected repeat delay. */ - protected int _siid = -1; - - /** The unique interval identifier for the key repeat interval. */ - protected int _iid = -1; + /** True if we are a scheduled interval. */ + protected boolean _scheduled = false; /** The last time a key released event was received for this key. */ protected long _lastRelease; diff --git a/src/java/com/threerings/util/RobotPlayer.java b/src/java/com/threerings/util/RobotPlayer.java index 96bd82293..f550dc976 100644 --- a/src/java/com/threerings/util/RobotPlayer.java +++ b/src/java/com/threerings/util/RobotPlayer.java @@ -1,5 +1,5 @@ // -// $Id: RobotPlayer.java,v 1.3 2004/08/27 02:20:36 mdb Exp $ +// $Id$ // // Narya library - tools for developing networked games // Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved @@ -27,7 +27,6 @@ import java.util.ArrayList; import com.samskivert.swing.Controller; import com.samskivert.util.CollectionUtil; import com.samskivert.util.Interval; -import com.samskivert.util.IntervalManager; import com.threerings.util.RandomUtil; @@ -41,7 +40,7 @@ import com.threerings.util.RandomUtil; * events can be simulated in that fashion (e.g., a right shift key * press), and this seemed somehow more proper in any case. */ -public class RobotPlayer implements Interval +public class RobotPlayer extends Interval { /** * Constructs a robot player. @@ -62,14 +61,13 @@ public class RobotPlayer implements Interval */ public void setActive (boolean active) { - if (active && !isActive()) { - // start the robot player - _iid = IntervalManager.register(this, _robotDelay, null, true); - - } else if (!active && isActive()) { - // stop the robot player - IntervalManager.remove(_iid); - _iid = -1; + if (active != _active) { + if (active) { + schedule(_robotDelay, true); + } else { + cancel(); // stop the robot player + } + _active = active; } } @@ -93,11 +91,11 @@ public class RobotPlayer implements Interval */ public boolean isActive () { - return (_iid != -1); + return _active; } // documentation inherited - public void intervalExpired (int id, Object arg) + public void expired () { // post a random key press command int idx = RandomUtil.getInt(_press.size()); @@ -109,8 +107,8 @@ public class RobotPlayer implements Interval /** The default robot delay. */ protected static final long DEFAULT_ROBOT_DELAY = 500L; - /** The unique robot interval identifier. */ - protected int _iid = -1; + /** Whether the robot is active or not. */ + protected boolean _active = false; /** The milliseconds between posting each action command. */ protected long _robotDelay = DEFAULT_ROBOT_DELAY; diff --git a/src/java/com/threerings/whirled/server/SceneManager.java b/src/java/com/threerings/whirled/server/SceneManager.java index 6a039ca72..080bd4cd7 100644 --- a/src/java/com/threerings/whirled/server/SceneManager.java +++ b/src/java/com/threerings/whirled/server/SceneManager.java @@ -1,5 +1,5 @@ // -// $Id: SceneManager.java,v 1.19 2004/08/27 02:20:43 mdb Exp $ +// $Id$ // // Narya library - tools for developing networked games // Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved @@ -107,7 +107,7 @@ public class SceneManager extends PlaceManager // Wait until us and all of our subclasses have completely finished // running didStartup prior to registering the scene as being ready. - PresentsServer.omgr.postUnit(new Runnable() { + PresentsServer.omgr.postRunnable(new Runnable() { public void run () { _screg.sceneManagerDidStart(SceneManager.this); }