Fix potential (but rare) rewind savestate corruption when threaded option is enabled.

This commit is contained in:
jdpurcell 2015-01-18 15:38:49 +00:00
parent 91ffc17aae
commit 45ae0bb207
1 changed files with 15 additions and 6 deletions

View File

@ -6,14 +6,10 @@ namespace BizHawk.Client.Common
{
public class RewindThreader : IDisposable
{
// adelikat: tweak this to test performance with threading or not with threading
// natt: IEmulator.SaveStateBinary() returns a byte[] but you're not allowed to modify it,
// and if the method is called again, the data from a previous call could be invalidated.
// GPGX and N64 make use of this property. if you set IsThreaded = true, you'll need to Clone() in many cases,
// which will kill N64 for sure...
public static bool IsThreaded = false;
private readonly ConcurrentQueue<Job> _jobs = new ConcurrentQueue<Job>();
private readonly ConcurrentStack<byte[]> _stateBufferPool = new ConcurrentStack<byte[]>();
private readonly EventWaitHandle _ewh;
private readonly EventWaitHandle _ewh2;
private readonly Thread _thread;
@ -75,10 +71,22 @@ namespace BizHawk.Client.Common
return;
}
byte[] savestateCopy = null;
while (_stateBufferPool.TryPop(out savestateCopy) && savestateCopy.Length != coreSavestate.Length)
{
savestateCopy = null;
}
if (savestateCopy == null)
{
savestateCopy = new byte[coreSavestate.Length];
}
Buffer.BlockCopy(coreSavestate, 0, savestateCopy, 0, coreSavestate.Length);
var job = new Job
{
Type = JobType.Capture,
CoreState = coreSavestate
CoreState = savestateCopy
};
DoSafeEnqueue(job);
}
@ -101,6 +109,7 @@ namespace BizHawk.Client.Common
if (job.Type == JobType.Capture)
{
_rewinder.RunCapture(job.CoreState);
_stateBufferPool.Push(job.CoreState);
}
if (job.Type == JobType.Rewind)