[Threading] Make VA thread safe
This fixes an issue for dedis
This commit is contained in:
parent
7af0f7368c
commit
9f50c260c8
@ -43,5 +43,8 @@ namespace Components
|
|||||||
Utils::Hook(0x627695, 0x627040, HOOK_CALL).install()->quick();
|
Utils::Hook(0x627695, 0x627040, HOOK_CALL).install()->quick();
|
||||||
Utils::Hook(0x43D1C7, Threading::PacketEventStub, HOOK_JUMP).install()->quick();
|
Utils::Hook(0x43D1C7, Threading::PacketEventStub, HOOK_JUMP).install()->quick();
|
||||||
Utils::Hook(0x6272E3, Threading::FrameEpilogueStub, HOOK_JUMP).install()->quick();
|
Utils::Hook(0x6272E3, Threading::FrameEpilogueStub, HOOK_JUMP).install()->quick();
|
||||||
|
|
||||||
|
// Make VA thread safe
|
||||||
|
Utils::Hook(0x4785B0, Utils::String::VA, HOOK_JUMP).install()->quick();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,25 +3,51 @@
|
|||||||
#include "base128.h"
|
#include "base128.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define VA_BUFFER_COUNT 32
|
|
||||||
#define VA_BUFFER_SIZE 65536
|
|
||||||
|
|
||||||
namespace Utils
|
namespace Utils
|
||||||
{
|
{
|
||||||
namespace String
|
namespace String
|
||||||
{
|
{
|
||||||
|
VAProvider::VAProvider(size_t buffers) : currentBuffer(0)
|
||||||
|
{
|
||||||
|
this->stringBuffers.resize(buffers);
|
||||||
|
}
|
||||||
|
|
||||||
|
char* VAProvider::get(const char* format, va_list ap)
|
||||||
|
{
|
||||||
|
++this->currentBuffer %= this->stringBuffers.size();
|
||||||
|
auto& buffer = this->stringBuffers[this->currentBuffer];
|
||||||
|
|
||||||
|
if (!buffer.first || !buffer.second)
|
||||||
|
{
|
||||||
|
buffer.first = 256;
|
||||||
|
if (buffer.second) this->allocator.free(buffer.second);
|
||||||
|
buffer.second = this->allocator.allocateArray<char>(buffer.first + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
while(true)
|
||||||
|
{
|
||||||
|
int res = vsnprintf_s(buffer.second, buffer.first, _TRUNCATE, format, ap);
|
||||||
|
if (res > 0) break; // Success
|
||||||
|
if (res == 0) return ""; // Error
|
||||||
|
|
||||||
|
buffer.first *= 2;
|
||||||
|
|
||||||
|
this->allocator.free(buffer.second);
|
||||||
|
buffer.second = this->allocator.allocateArray<char>(buffer.first + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return buffer.second;
|
||||||
|
}
|
||||||
|
|
||||||
const char *VA(const char *fmt, ...)
|
const char *VA(const char *fmt, ...)
|
||||||
{
|
{
|
||||||
static char g_vaBuffer[VA_BUFFER_COUNT][VA_BUFFER_SIZE];
|
static thread_local VAProvider provider;
|
||||||
static int g_vaNextBufferIndex = 0;
|
|
||||||
|
|
||||||
va_list ap;
|
va_list ap;
|
||||||
va_start(ap, fmt);
|
va_start(ap, fmt);
|
||||||
char* dest = g_vaBuffer[g_vaNextBufferIndex];
|
const char* result = provider.get(fmt, ap);
|
||||||
vsnprintf_s(g_vaBuffer[g_vaNextBufferIndex], VA_BUFFER_SIZE, fmt, ap);
|
|
||||||
g_vaNextBufferIndex = (g_vaNextBufferIndex + 1) % VA_BUFFER_COUNT;
|
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
return dest;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string ToLower(std::string input)
|
std::string ToLower(std::string input)
|
||||||
|
@ -4,6 +4,20 @@ namespace Utils
|
|||||||
{
|
{
|
||||||
namespace String
|
namespace String
|
||||||
{
|
{
|
||||||
|
class VAProvider
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
VAProvider(size_t buffers = 8);
|
||||||
|
|
||||||
|
char* get(const char* format, va_list ap);
|
||||||
|
|
||||||
|
private:
|
||||||
|
size_t currentBuffer;
|
||||||
|
std::vector<std::pair<size_t,char*>> stringBuffers;
|
||||||
|
|
||||||
|
Utils::Memory::Allocator allocator;
|
||||||
|
};
|
||||||
|
|
||||||
const char *VA(const char *fmt, ...);
|
const char *VA(const char *fmt, ...);
|
||||||
|
|
||||||
int IsSpace(int c);
|
int IsSpace(int c);
|
||||||
|
Loading…
Reference in New Issue
Block a user