[String] Use leak-free local storage implementation of VA

This commit is contained in:
momo5502 2017-06-02 22:05:32 +02:00
parent a739e3bc8d
commit 49c0b7d3a1
2 changed files with 12 additions and 33 deletions

View File

@ -9,7 +9,7 @@ namespace Utils
{ {
const char *VA(const char *fmt, ...) const char *VA(const char *fmt, ...)
{ {
static VAProvider<8, 256> provider; static thread_local VAProvider<8, 256> provider;
va_list ap; va_list ap;
va_start(ap, fmt); va_start(ap, fmt);

View File

@ -8,38 +8,29 @@ namespace Utils
class VAProvider class VAProvider
{ {
public: public:
VAProvider() : currentBuffer(0) {}
typename std::enable_if<(Buffers != 0 && MinBufferSize != 0), char*>::type typename std::enable_if<(Buffers != 0 && MinBufferSize != 0), char*>::type
get(const char* format, va_list ap) get(const char* format, va_list ap)
{ {
std::lock_guard<std::mutex> _(this->accessMutex); ++this->currentBuffer %= ARRAYSIZE(this->stringPool);
auto entry = &this->stringPool[this->currentBuffer];
auto threadBuffers = this->stringBuffers.find(std::this_thread::get_id()); if (!entry->size || !entry->buffer)
if (threadBuffers == this->stringBuffers.end())
{ {
this->stringBuffers[std::this_thread::get_id()] = Pool(); *entry = Entry(MinBufferSize);
threadBuffers = this->stringBuffers.find(std::this_thread::get_id());
}
if (!threadBuffers->second.stringPool.size()) threadBuffers->second.stringPool.resize(Buffers);
++threadBuffers->second.currentBuffer %= threadBuffers->second.stringPool.size();
auto& entry = threadBuffers->second.stringPool[threadBuffers->second.currentBuffer];
if (!entry.size || !entry.buffer)
{
entry = Entry(MinBufferSize);
} }
while (true) while (true)
{ {
int res = vsnprintf_s(entry.buffer, entry.size, _TRUNCATE, format, ap); int res = vsnprintf_s(entry->buffer, entry->size, _TRUNCATE, format, ap);
if (res > 0) break; // Success if (res > 0) break; // Success
if (res == 0) return ""; // Error if (res == 0) return ""; // Error
entry.doubleSize(); entry->doubleSize();
} }
return entry.buffer; return entry->buffer;
} }
private: private:
@ -73,20 +64,8 @@ namespace Utils
char* buffer; char* buffer;
}; };
class Pool
{
public:
Pool() : currentBuffer(0)
{
this->stringPool.resize(Buffers);
}
size_t currentBuffer; size_t currentBuffer;
std::vector<Entry> stringPool; Entry stringPool[Buffers];
};
std::mutex accessMutex;
std::unordered_map<std::thread::id, Pool> stringBuffers;
}; };
const char *VA(const char *fmt, ...); const char *VA(const char *fmt, ...);