From: <m97...@us...> - 2010-06-29 17:49:22
|
Revision: 11563 http://openmsx.svn.sourceforge.net/openmsx/?rev=11563&view=rev Author: m9710797 Date: 2010-06-29 17:49:13 +0000 (Tue, 29 Jun 2010) Log Message: ----------- Simplified algorithm to pick the to-be saved snapshots (in a replay file). Modified Paths: -------------- openmsx/trunk/src/EmuDuration.hh openmsx/trunk/src/ReverseManager.cc Modified: openmsx/trunk/src/EmuDuration.hh =================================================================== --- openmsx/trunk/src/EmuDuration.hh 2010-06-27 16:16:37 UTC (rev 11562) +++ openmsx/trunk/src/EmuDuration.hh 2010-06-29 17:49:13 UTC (rev 11563) @@ -67,6 +67,8 @@ { return EmuDuration(time * fact); } const EmuDuration operator/(unsigned fact) const { return EmuDuration(time / fact); } + const EmuDuration divRoundUp(unsigned fact) const + { return EmuDuration((time + fact - 1) / fact); } unsigned operator/(EmuDuration::param d) const { uint64 result = time / d.time; Modified: openmsx/trunk/src/ReverseManager.cc =================================================================== --- openmsx/trunk/src/ReverseManager.cc 2010-06-27 16:16:37 UTC (rev 11562) +++ openmsx/trunk/src/ReverseManager.cc 2010-06-29 17:49:13 UTC (rev 11563) @@ -22,7 +22,6 @@ #include "checked_cast.hh" #include "ref.hh" #include <cassert> -#include <cmath> using std::string; using std::vector; @@ -30,14 +29,14 @@ namespace openmsx { -// Time between two snapshots in seconds +// Time between two snapshots (in seconds) static const double SNAPSHOT_PERIOD = 1.0; // Max number of snapshots in a replay static const unsigned MAX_NOF_SNAPSHOTS = 10; -// Min distance between snapshots in replay in seconds -static const double MIN_SNAPSHOT_DISTANCE = 60.0; +// Min distance between snapshots in replay (in seconds) +static const EmuDuration MIN_PARTITION_LENGTH = EmuDuration(60.0); static const string REPLAY_DIR = "replays"; @@ -396,7 +395,8 @@ void ReverseManager::saveReplay(const vector<TclObject*>& tokens, TclObject& result) { - if (history.chunks.empty()) { + const Chunks& chunks = history.chunks; + if (chunks.empty()) { throw CommandException("No recording..."); } @@ -423,7 +423,7 @@ // restore first snapshot to be able to serialize it to a file Reactor::Board initialBoard = reactor.createEmptyMotherBoard(); - MemInputArchive in(*history.chunks.begin()->second.savestate); + MemInputArchive in(*chunks.begin()->second.savestate); in.serialize("machine", *initialBoard); // update re-record-count, see comment in goTo(). @@ -431,42 +431,34 @@ replay.motherBoards.push_back(initialBoard); // determine which extra snapshots to put in the replay - if (history.chunks.size() > 1) { - double length = (getEndTime() - - initialBoard->getCurrentTime()).toDouble() + - SNAPSHOT_PERIOD; // add a little extra time for when - // the last snapshot is exactly on the end of the time line - double windowSize = std::max(MIN_SNAPSHOT_DISTANCE, length / MAX_NOF_SNAPSHOTS); - // the purpose of the rest of this scope is to take the youngest - // snapshot for each time partition of windowSize - Chunks::const_iterator it = history.chunks.begin(); - ++it; // don't include the initial one - unsigned partitionNr = 0; - unsigned lastAddedSnapshotNr = it->first; - // look over the whole timeline (maybe a bit more, but certainly not - // less) in time partitions of windowSize - while (partitionNr < unsigned(ceil(length / windowSize))) { - partitionNr++; - PRT_DEBUG("Partition " << partitionNr << ", edge: " << (partitionNr * windowSize) << ", length: " << length); - // find first snapshot newer than right side of window - while ((((it->second).time - EmuTime::zero).toDouble() < (partitionNr * windowSize)) && (it != history.chunks.end())) ++it; - // take the previous to get back in the window (or, if none - // present in the window, we'll end up with previous snapshot) - // if it was the end() iterator, we'll end up with the last one + const EmuTime& startTime = chunks.begin()->second.time; + const EmuTime& endTime = chunks.rbegin()->second.time; + EmuDuration totalLength = endTime - startTime; + EmuDuration partitionLength = totalLength.divRoundUp(MAX_NOF_SNAPSHOTS); + partitionLength = std::max(MIN_PARTITION_LENGTH, partitionLength); + EmuTime nextPartitionEnd = startTime + partitionLength; + Chunks::const_iterator it = chunks.begin(); + Chunks::const_iterator lastAddedIt = chunks.begin(); // already added + while (it != chunks.end()) { + ++it; + if (it == chunks.end() || (it->second.time > nextPartitionEnd)) { --it; - if (it->first != lastAddedSnapshotNr) { + assert(it->second.time <= nextPartitionEnd); + if (it != lastAddedIt) { // this is a new one, add it to the list of snapshots Reactor::Board board = reactor.createEmptyMotherBoard(); MemInputArchive in(*it->second.savestate); in.serialize("machine", *board); replay.motherBoards.push_back(board); - lastAddedSnapshotNr = it->first; + lastAddedIt = it; } + ++it; + while (it != chunks.end() && it->second.time > nextPartitionEnd) { + nextPartitionEnd += partitionLength; + } } - // we should have arrived at the last snapshot now - PRT_DEBUG("lastadded: " << lastAddedSnapshotNr << ", last snapshot: " << history.chunks.rbegin()->first << ", with time: " << ((history.chunks.rbegin()->second).time - EmuTime::zero).toDouble()); - assert(lastAddedSnapshotNr == history.chunks.rbegin()->first); } + assert(lastAddedIt == --chunks.end()); // last snapshot must be included // add sentinel when there isn't one yet bool addSentinel = history.events.empty() || This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |