From 66bcd2fd685b0421dd4884755c260703b64e9049 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sat, 5 Dec 2015 01:05:24 +0100 Subject: [PATCH] Write save games to a memory stream first Two motivations for doing this: - If the user chooses to overwrite existing save file, and there is an exception during the save process, the existing file will not be lost. - Many small writes to a file are slow. Very slow. Writing to memory first then writing the completed file to disk appears to be ~500% faster. --- apps/openmw/mwstate/statemanagerimp.cpp | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/apps/openmw/mwstate/statemanagerimp.cpp b/apps/openmw/mwstate/statemanagerimp.cpp index b76d9eae5..b5426bc77 100644 --- a/apps/openmw/mwstate/statemanagerimp.cpp +++ b/apps/openmw/mwstate/statemanagerimp.cpp @@ -207,7 +207,9 @@ void MWState::StateManager::saveGame (const std::string& description, const Slot else slot = getCurrentCharacter()->updateSlot (slot, profile); - boost::filesystem::ofstream stream (slot->mPath, std::ios::binary); + // Write to a memory stream first. If there is an exception during the save process, we don't want to trash the + // existing save file we are overwriting. + std::stringstream stream; ESM::ESMWriter writer; @@ -262,7 +264,14 @@ void MWState::StateManager::saveGame (const std::string& description, const Slot writer.close(); if (stream.fail()) - throw std::runtime_error("Write operation failed"); + throw std::runtime_error("Write operation failed (memory stream)"); + + // All good, write to file + boost::filesystem::ofstream filestream (slot->mPath, std::ios::binary); + filestream << stream.rdbuf(); + + if (filestream.fail()) + throw std::runtime_error("Write operation failed (file stream)"); Settings::Manager::setString ("character", "Saves", slot->mPath.parent_path().filename().string());