Skip to content

Instantly share code, notes, and snippets.

@pCYSl5EDgo
Last active April 13, 2020 03:53
Show Gist options
  • Save pCYSl5EDgo/fc3847f4c4a3b58c0dbc47d2c960620d to your computer and use it in GitHub Desktop.
Save pCYSl5EDgo/fc3847f4c4a3b58c0dbc47d2c960620d to your computer and use it in GitHub Desktop.
using System;
using System.IO;
using System.Threading.Tasks;
class SaveData
{
// 中身は適切に書いてね
}
class SaveDataSerializer
{
public byte[] Serialize(SaveData data, int turnCount, DateTime savindTime)
{
// 中身は適切に書いてね
return Array.Empty<byte>();
}
}
class Saver
{
private const int backupInterval = 12;
private readonly FileInfo normalSaveFile;
private readonly FileInfo backupSaveFile;
private readonly SaveData data;
private readonly SaveDataSerializer serializer;
private Task previousNormalSavingTask;
private FileStream normalFileStream;
public Saver(SaveData data, string normalSaveFilePath, string backupSaveFilePath, SaveDataSerializer serializer)
{
normalSaveFile = new FileInfo(normalSaveFilePath);
backupSaveFile = new FileInfo(backupSaveFilePath);
previousNormalSavingTask = Task.CompletedTask;
this.data = data;
this.serializer = serializer;
}
public void Save(int currentTurnCount)
{
if (currentTurnCount <= 0 || (currentTurnCount / backupInterval) * backupInterval != currentTurnCount)
{
SaveWithoutBackup(currentTurnCount);
}
else
{
SaveWithBackup(currentTurnCount);
}
}
private void SaveWithBackup(int turnCount)
{
var isPreviousTaskEnded = previousNormalSavingTask.IsCompleted || previousNormalSavingTask.IsCanceled || previousNormalSavingTask.IsFaulted;
if (isPreviousTaskEnded)
{
SaveWithBackupInternal(turnCount);
}
else
{
previousNormalSavingTask.ContinueWith(SaveWithBackUpInternalContinuation, (this, turnCount));
}
}
private static void SaveWithBackUpInternalContinuation(Task _, object obj)
{
var (@this, turnCount) = (ValueTuple<Saver, int>)obj;
@this.SaveWithBackupInternal(turnCount);
}
private void SaveWithBackupInternal(int turnCount)
{
normalFileStream = normalSaveFile.OpenWrite();
var bytes = serializer.Serialize(data, turnCount, DateTime.Now);
previousNormalSavingTask = normalFileStream.WriteAsync(bytes, 0, bytes.Length)
.ContinueWith(FileStreamDisposingContinuation, normalFileStream)
.ContinueWith(CopyContinuation, (normalSaveFile.FullName, backupSaveFile.FullName));
}
private static void FileStreamDisposingContinuation(Task _, object obj)
{
var fileStream = (FileStream)obj;
fileStream.Dispose();
}
private static void CopyContinuation(Task _, object obj)
{
var (normal, backup) = (ValueTuple<string, string>)obj;
File.Copy(normal, backup, overwrite: true);
}
private void SaveWithoutBackup(int turnCount)
{
var isPreviousTaskEnded = previousNormalSavingTask.IsCompleted || previousNormalSavingTask.IsCanceled || previousNormalSavingTask.IsFaulted;
if (isPreviousTaskEnded)
{
SaveWithoutBackupInternal(turnCount);
}
else
{
previousNormalSavingTask.ContinueWith(SaveWithoutBackUpInternalContinuation, (this, turnCount));
}
}
private static void SaveWithoutBackUpInternalContinuation(Task _, object obj)
{
var (@this, turnCount) = (ValueTuple<Saver, int>)obj;
@this.SaveWithoutBackupInternal(turnCount);
}
private void SaveWithoutBackupInternal(int turnCount)
{
normalFileStream = normalSaveFile.OpenWrite();
var bytes = serializer.Serialize(data, turnCount, DateTime.Now);
previousNormalSavingTask = normalFileStream.WriteAsync(bytes, 0, bytes.Length)
.ContinueWith(FileStreamDisposingContinuation, normalFileStream);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment