From c8f80ceee0d0bb6bd376c5e3a526ef483003c9be Mon Sep 17 00:00:00 2001 From: momo5502 Date: Sun, 4 Jun 2017 13:46:50 +0200 Subject: [PATCH] [String] Use alternateive VAProvider when uninitializing Using thread-local VAProviders in the uninitialization routine is not possible, as thread storage has already been destroyed --- src/Components/Loader.cpp | 9 +++++++++ src/Components/Loader.hpp | 2 ++ src/Utils/String.cpp | 7 ++++++- src/Utils/String.hpp | 13 +++++++++---- 4 files changed, 26 insertions(+), 5 deletions(-) diff --git a/src/Components/Loader.cpp b/src/Components/Loader.cpp index c2edf063..162037d7 100644 --- a/src/Components/Loader.cpp +++ b/src/Components/Loader.cpp @@ -4,6 +4,7 @@ namespace Components { bool Loader::Pregame = true; bool Loader::Postgame = false; + bool Loader::Uninitializing = false; bool Loader::ComInitialized = false; std::vector Loader::Components; @@ -17,6 +18,11 @@ namespace Components return Loader::Postgame; } + bool Loader::IsUninitializing() + { + return Loader::Uninitializing; + } + bool Loader::IsComInitialized() { return Loader::ComInitialized; @@ -26,6 +32,7 @@ namespace Components { Loader::Pregame = true; Loader::Postgame = false; + Loader::Uninitializing = false; Utils::Memory::GetAllocator()->clear(); Loader::ComInitialized = false; @@ -106,6 +113,7 @@ namespace Components void Loader::Uninitialize() { + Loader::Uninitializing = true; Loader::PreDestroyNoPostGame(); std::reverse(Loader::Components.begin(), Loader::Components.end()); @@ -124,6 +132,7 @@ namespace Components Utils::Memory::GetAllocator()->clear(); if (!Loader::PerformingUnitTests() && !Utils::IsWineEnvironment() && Loader::ComInitialized) CoUninitialize(); + Loader::Uninitializing = false; } void Loader::PreDestroy() diff --git a/src/Components/Loader.hpp b/src/Components/Loader.hpp index f5ddc630..e3859d2f 100644 --- a/src/Components/Loader.hpp +++ b/src/Components/Loader.hpp @@ -37,6 +37,7 @@ namespace Components static bool IsPregame(); static bool IsPostgame(); + static bool IsUninitializing(); static bool IsComInitialized(); template @@ -56,6 +57,7 @@ namespace Components private: static bool Pregame; static bool Postgame; + static bool Uninitializing; static bool ComInitialized; static std::vector Components; }; diff --git a/src/Utils/String.cpp b/src/Utils/String.cpp index 4e4248aa..d319e6eb 100644 --- a/src/Utils/String.cpp +++ b/src/Utils/String.cpp @@ -9,11 +9,16 @@ namespace Utils { const char *VA(const char *fmt, ...) { + static VAProvider<4, 100> globalProvider; static thread_local VAProvider<8, 256> provider; va_list ap; va_start(ap, fmt); - const char* result = provider.get(fmt, ap); + + const char* result; + if(Components::Loader::IsUninitializing()) result = globalProvider.get(fmt, ap); + else result = provider.get(fmt, ap); + va_end(ap); return result; } diff --git a/src/Utils/String.hpp b/src/Utils/String.hpp index d4646947..08ef10c8 100644 --- a/src/Utils/String.hpp +++ b/src/Utils/String.hpp @@ -8,17 +8,19 @@ namespace Utils class VAProvider { public: - VAProvider() : currentBuffer(0) {} + static_assert(Buffers != 0 && MinBufferSize != 0, "Buffers and MinBufferSize mustn't be 0"); - typename std::enable_if<(Buffers != 0 && MinBufferSize != 0), char*>::type - get(const char* format, va_list ap) + VAProvider() : currentBuffer(0) {} + ~VAProvider() {} + + char* get(const char* format, va_list ap) { ++this->currentBuffer %= ARRAYSIZE(this->stringPool); auto entry = &this->stringPool[this->currentBuffer]; if (!entry->size || !entry->buffer) { - *entry = Entry(MinBufferSize); + throw std::runtime_error("String pool not initialized"); } while (true) @@ -46,6 +48,8 @@ namespace Utils ~Entry() { if(this->buffer) Utils::Memory::GetAllocator()->free(this->buffer); + this->size = 0; + this->buffer = nullptr; } void allocate() @@ -64,6 +68,7 @@ namespace Utils char* buffer; }; + size_t currentBuffer; Entry stringPool[Buffers]; };