From 44a1a7cdbee8b267ed33055e89e9491843d30fc7 Mon Sep 17 00:00:00 2001 From: Shawn Hoffman Date: Mon, 1 Sep 2014 22:15:17 -0700 Subject: [PATCH] move the decision to delay raw memcard flushes out of the thread. This allows the flush to work better with games which hammer memcard accesses over short periods as it delays more of the work. --- Source/Core/Core/HW/GCMemcardRaw.cpp | 33 ++++++++++------------------ Source/Core/Core/HW/GCMemcardRaw.h | 3 +++ 2 files changed, 14 insertions(+), 22 deletions(-) diff --git a/Source/Core/Core/HW/GCMemcardRaw.cpp b/Source/Core/Core/HW/GCMemcardRaw.cpp index 116abd78a2..4366929ba1 100644 --- a/Source/Core/Core/HW/GCMemcardRaw.cpp +++ b/Source/Core/Core/HW/GCMemcardRaw.cpp @@ -12,6 +12,8 @@ #define SIZE_TO_Mb (1024 * 8 * 16) #define MC_HDR_SIZE 0xA000 +const std::chrono::seconds MemoryCard::s_flush_interval{ 15 }; + MemoryCard::MemoryCard(std::string filename, int _card_index, u16 sizeMb) : MemoryCardBase(_card_index, sizeMb) , m_filename(filename) @@ -44,6 +46,7 @@ MemoryCard::MemoryCard(std::string filename, int _card_index, u16 sizeMb) // Class members (including inherited ones) have now been initialized, so // it's safe to startup the flush thread (which reads them). + m_last_flush = std::chrono::steady_clock::now(); m_flush_buffer = std::make_unique(memory_card_size); m_flush_thread = std::thread(&MemoryCard::FlushThread, this); } @@ -75,29 +78,10 @@ void MemoryCard::FlushThread() Common::SetCurrentThreadName( StringFromFormat("Memcard%x-Flush", card_index).c_str()); - const auto flush_interval = std::chrono::seconds(15); - auto last_flush = std::chrono::steady_clock::now(); - bool dirty = false; - for (;;) { - bool triggered = m_flush_trigger.WaitFor(flush_interval); + m_flush_trigger.Wait(); bool do_exit = m_is_exiting.IsSet(); - if (triggered) - { - dirty = true; - } - // Delay the flush if we're not exiting or if the event timed out and - // the state isn't dirty. - if (!do_exit) - { - auto now = std::chrono::steady_clock::now(); - if (now - last_flush < flush_interval || !dirty) - { - continue; - } - last_flush = now; - } // Opening the file is purposefully done each iteration to ensure the // file doesn't disappear out from under us after the first check. @@ -134,8 +118,6 @@ void MemoryCard::FlushThread() pFile.WriteBytes(&m_flush_buffer[0], memory_card_size); } - dirty = false; - if (!do_exit) { Core::DisplayMessage( @@ -156,6 +138,13 @@ void MemoryCard::FlushThread() // be done now. void MemoryCard::TryFlush() { + auto now = std::chrono::steady_clock::now(); + if (now - m_last_flush < s_flush_interval) + { + return; + } + m_last_flush = now; + if (m_flush_mutex.try_lock()) { memcpy(&m_flush_buffer[0], &m_memcard_data[0], memory_card_size); diff --git a/Source/Core/Core/HW/GCMemcardRaw.h b/Source/Core/Core/HW/GCMemcardRaw.h index 419af8732b..68c3216c62 100644 --- a/Source/Core/Core/HW/GCMemcardRaw.h +++ b/Source/Core/Core/HW/GCMemcardRaw.h @@ -4,6 +4,7 @@ #pragma once +#include #include #include "Common/Event.h" #include "Common/Flag.h" @@ -34,4 +35,6 @@ private: Common::Event m_flush_trigger; Common::Flag m_is_exiting; std::unique_ptr m_flush_buffer; + std::chrono::steady_clock::time_point m_last_flush; + static const std::chrono::seconds s_flush_interval; };