[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, ...)
{
static VAProvider<8, 256> provider;
static thread_local VAProvider<8, 256> provider;
va_list ap;
va_start(ap, fmt);

View File

@ -8,38 +8,29 @@ namespace Utils
class VAProvider
{
public:
VAProvider() : currentBuffer(0) {}
typename std::enable_if<(Buffers != 0 && MinBufferSize != 0), char*>::type
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 (threadBuffers == this->stringBuffers.end())
if (!entry->size || !entry->buffer)
{
this->stringBuffers[std::this_thread::get_id()] = Pool();
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);
*entry = Entry(MinBufferSize);
}
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) return ""; // Error
entry.doubleSize();
entry->doubleSize();
}
return entry.buffer;
return entry->buffer;
}
private:
@ -73,20 +64,8 @@ namespace Utils
char* buffer;
};
class Pool
{
public:
Pool() : currentBuffer(0)
{
this->stringPool.resize(Buffers);
}
size_t currentBuffer;
std::vector<Entry> stringPool;
};
std::mutex accessMutex;
std::unordered_map<std::thread::id, Pool> stringBuffers;
size_t currentBuffer;
Entry stringPool[Buffers];
};
const char *VA(const char *fmt, ...);