From 981deb3b6b5064051a979e412982a0c1c09b9b69 Mon Sep 17 00:00:00 2001 From: Ray Greenwell Date: Thu, 30 Mar 2006 01:08:32 +0000 Subject: [PATCH] Fixed two bugs with delta calculation: - if a pong response took more than 5 seconds to receive, another ping would be sent. When the pong finally arrived the delta would be calculated using the most recently sent ping. Fix: don't send more pings while waiting on a pong. - After a pong is received, the _deltas array is mangled while calculating the server delta, making subsequent pongs possibly overwrite earlier calculated deltas. Fix: calculate using a copy. Also, changed the delta calculation to be the mean of the deltas rather than the median. Left code in to do it both ways if this change was not kosher... git-svn-id: svn+ssh://src.earth.threerings.net/narya/trunk@3990 542714f4-19e9-0310-aa3c-eee0fc999fb1 --- .../threerings/presents/client/Client.java | 20 +++++----- .../presents/client/DeltaCalculator.java | 38 +++++++++++++++++-- 2 files changed, 43 insertions(+), 15 deletions(-) diff --git a/src/java/com/threerings/presents/client/Client.java b/src/java/com/threerings/presents/client/Client.java index 091217446..4541bb3f1 100644 --- a/src/java/com/threerings/presents/client/Client.java +++ b/src/java/com/threerings/presents/client/Client.java @@ -483,7 +483,7 @@ public class Client if (_dcalc.isDone()) { Log.debug("Time offset from server: " + _serverDelta + "ms."); _dcalc = null; - } else { + } else if (_dcalc.shouldSendPing()) { // otherwise, send another ping PingRequest req = new PingRequest(); _comm.postMessage(req); @@ -621,17 +621,15 @@ public class Client */ void gotPong (PongResponse pong) { - // if we're not calculating our client/server time delta, then we - // don't need to do anything with the pong - if (_dcalc == null) { - return; + // if we're not currently calculating our client/server delta, then + // we can throw away the pong + if (_dcalc != null) { + // we update the delta after every receipt so as to immediately + // obtain an estimate of the clock delta and then refine it as + // more packets come in + _dcalc.gotPong(pong); + _serverDelta = _dcalc.getTimeDelta(); } - - // we update the delta after every receipt so as to immediately - // obtain an estimate of the clock delta and then refine it as - // more packets come in - _dcalc.gotPong(pong); - _serverDelta = _dcalc.getTimeDelta(); } /** diff --git a/src/java/com/threerings/presents/client/DeltaCalculator.java b/src/java/com/threerings/presents/client/DeltaCalculator.java index 02fa9c09e..bb82c1915 100644 --- a/src/java/com/threerings/presents/client/DeltaCalculator.java +++ b/src/java/com/threerings/presents/client/DeltaCalculator.java @@ -1,5 +1,5 @@ // -// $Id: DeltaCalculator.java,v 1.8 2004/10/22 01:19:55 mdb Exp $ +// $Id$ // // Narya library - tools for developing networked games // Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved @@ -45,6 +45,14 @@ public class DeltaCalculator _deltas = new long[CLOCK_SYNC_PING_COUNT]; } + /** + * Should we send another ping? + */ + public boolean shouldSendPing () + { + return (_ping == null) && !isDone(); + } + /** * Must be called when a ping message is sent to the server. */ @@ -69,6 +77,7 @@ public class DeltaCalculator // make a note of when the ping message was sent and when the pong // response was received (both in client time) long send = _ping.getPackStamp(), recv = pong.getUnpackStamp(); + _ping = null; // clear out the saved sent ping // make a note of when the pong response was sent (in server time) // and the processing delay incurred on the server @@ -93,9 +102,30 @@ public class DeltaCalculator */ public long getTimeDelta () { - // sort the estimates and return one from the middle - Arrays.sort(_deltas); - return _deltas[_deltas.length/2]; + if (_iter == 0) { // no responses yet + return 0L; + } + + if (true) { + // return the mean + long est = 0; + for (int ii=0; ii < _iter; ii++) { + est += _deltas[ii]; + } + return (est / _iter); + + } else { + // return the median value + + // copy the deltas array so that we don't alter things before + // all pongs have arrived + long[] deltasCopy = new long[_iter]; + System.arraycopy(_deltas, 0, deltasCopy, 0, _iter); + + // sort the estimates and return one from the middle + Arrays.sort(deltasCopy); + return deltasCopy[deltasCopy.length/2]; + } } /**