diff --git a/src/newgrf_config.cpp b/src/newgrf_config.cpp index 61d81eee0b..0d6f560ab5 100644 --- a/src/newgrf_config.cpp +++ b/src/newgrf_config.cpp @@ -344,6 +344,7 @@ static std::vector _grf_md5_pending; static std::condition_variable _grf_md5_full_cv; static std::condition_variable _grf_md5_empty_cv; static std::condition_variable _grf_md5_done_cv; +static std::atomic _abort_grf_scan; static const uint GRF_MD5_PENDING_MAX = 8; static void CalcGRFMD5SumFromState(const GRFMD5SumState &state) @@ -373,7 +374,7 @@ void CalcGRFMD5Thread() _grf_md5_pending.pop_back(); lk.unlock(); if (full) _grf_md5_full_cv.notify_one(); - CalcGRFMD5SumFromState(state); + if (!_abort_grf_scan.load(std::memory_order_relaxed)) CalcGRFMD5SumFromState(state); lk.lock(); } } @@ -728,6 +729,8 @@ public: bool GRFFileScanner::AddFile(const std::string &filename, size_t basepath_length, const std::string &tar_filename) { + if (_abort_grf_scan.load(std::memory_order_relaxed)) return false; + GRFConfig *c = new GRFConfig(filename.c_str() + basepath_length); bool added = FillGRFDetails(c, false); @@ -846,6 +849,11 @@ void ScanNewGRFFiles(NewGRFScanCallback *callback) } } +void AbortScanNewGRFFiles() +{ + _abort_grf_scan.store(true, std::memory_order_relaxed); +} + /** * Find a NewGRF in the scanned list. * @param grfid GRFID to look for, diff --git a/src/newgrf_config.h b/src/newgrf_config.h index 98d3a2f44b..2406b0ce6f 100644 --- a/src/newgrf_config.h +++ b/src/newgrf_config.h @@ -222,6 +222,7 @@ struct NewGRFScanCallback { size_t GRFGetSizeOfDataSection(FILE *f); void ScanNewGRFFiles(NewGRFScanCallback *callback); +void AbortScanNewGRFFiles(); const GRFConfig *FindGRFConfig(uint32 grfid, FindGRFConfigMode mode, const uint8 *md5sum = nullptr, uint32 desired_version = 0); GRFConfig *GetGRFConfig(uint32 grfid, uint32 mask = 0xFFFFFFFF); GRFConfig **CopyGRFConfigList(GRFConfig **dst, const GRFConfig *src, bool init_only); diff --git a/src/openttd.cpp b/src/openttd.cpp index 0b2eed731c..c057d35cee 100644 --- a/src/openttd.cpp +++ b/src/openttd.cpp @@ -1006,8 +1006,10 @@ int openttd_main(int argc, char *argv[]) CrashLog::MainThreadExitCheckPendingCrashlog(); + AbortScanNewGRFFiles(); WaitTillSaved(); WaitTillGeneratedWorld(); // Make sure any generate world threads have been joined. + WaitUntilModalProgressCompleted(); /* only save config if we have to */ if (_save_config) { diff --git a/src/progress.cpp b/src/progress.cpp index 57d96c3538..ea72fc51a5 100644 --- a/src/progress.cpp +++ b/src/progress.cpp @@ -9,6 +9,7 @@ #include "stdafx.h" #include "progress.h" +#include "video/video_driver.hpp" #include #include @@ -64,3 +65,22 @@ void SleepWhileModalProgress(int milliseconds) std::unique_lock lk(_modal_progress_cv_mutex); _modal_progress_cv.wait_for(lk, std::chrono::milliseconds(milliseconds), []{ return !_in_modal_progress; }); } + +void WaitUntilModalProgressCompleted() +{ + if (HasModalProgress()) { + _modal_progress_paint_mutex.unlock(); + _modal_progress_work_mutex.unlock(); + + { + std::unique_lock lk(_modal_progress_cv_mutex); + _modal_progress_cv.wait(lk, []{ return !_in_modal_progress; }); + } + + /* Modal progress thread may need blitter access while we are waiting for it. */ + VideoDriver::GetInstance()->ReleaseBlitterLock(); + _modal_progress_paint_mutex.lock(); + VideoDriver::GetInstance()->AcquireBlitterLock(); + _modal_progress_work_mutex.lock(); + } +} diff --git a/src/progress.h b/src/progress.h index f125b147be..16848252e0 100644 --- a/src/progress.h +++ b/src/progress.h @@ -40,6 +40,7 @@ static inline bool UseThreadedModelProgress() bool IsFirstModalProgressLoop(); void SetModalProgress(bool state); void SleepWhileModalProgress(int milliseconds); +void WaitUntilModalProgressCompleted(); extern std::mutex _modal_progress_work_mutex; extern std::mutex _modal_progress_paint_mutex;