Make atostr more thread safe

atostr now can hold 64 different results, and can be called from
multiple threads. Thus, a returned string buffer is valid until atostr
is called 64 more times.
This commit is contained in:
Stephen Seo 2019-09-03 16:19:47 +09:00
parent 05cb45ca14
commit 38eb06f105
3 changed files with 108 additions and 9 deletions

View file

@ -12,6 +12,10 @@
#define UDPC_ID_NO_REC_CHK 0x20000000
#define UDPC_ID_RESENDING 0x10000000
#define UDPC_ATOSTR_BUFCOUNT 64
#define UDPC_ATOSTR_BUFSIZE 16
#define UDPC_ATOSTR_SIZE (UDPC_ATOSTR_BUFCOUNT * UDPC_ATOSTR_BUFSIZE)
#include <atomic>
#include <bitset>
#include <chrono>
@ -229,7 +233,8 @@ public:
std::atomic_bool isAcceptNewConnections;
std::atomic_uint32_t protocolID;
std::atomic_uint_fast8_t loggingType;
char atostrBuf[16];
std::atomic_uint32_t atostrBufIndex;
char atostrBuf[UDPC_ATOSTR_SIZE];
int socketHandle;
struct sockaddr_in socketInfo;

View file

@ -77,6 +77,7 @@ loggingType(INFO),
#else
loggingType(WARNING),
#endif
atostrBufIndex(0),
rng_engine()
{
if(isThreaded) {
@ -1006,7 +1007,9 @@ const char *UDPC_atostr(UDPC_HContext ctx, uint32_t addr) {
if(!c) {
return nullptr;
}
int index = 0;
const uint32_t headIndex =
c->atostrBufIndex.fetch_add(UDPC_ATOSTR_BUFSIZE) % UDPC_ATOSTR_SIZE;
uint32_t index = headIndex;
for(int x = 0; x < 4; ++x) {
unsigned char temp = (addr >> (x * 8)) & 0xFF;
@ -1024,7 +1027,7 @@ const char *UDPC_atostr(UDPC_HContext ctx, uint32_t addr) {
}
c->atostrBuf[index] = 0;
return c->atostrBuf;
return c->atostrBuf + headIndex;
}
uint32_t UDPC_strtoa(const char *addrStr) {

View file

@ -4,18 +4,109 @@
#include <UDPC_Defines.hpp>
#include <cstring>
#include <future>
TEST(UDPC, atostr) {
UDPC::Context context(false);
UDPC_atostr((UDPC_HContext)&context, 0x0100007F);
EXPECT_EQ(std::strcmp(context.atostrBuf, "127.0.0.1"), 0);
const char* resultBuf;
UDPC_atostr((UDPC_HContext)&context, 0xFF08000A);
EXPECT_EQ(std::strcmp(context.atostrBuf, "10.0.8.255"), 0);
resultBuf = UDPC_atostr((UDPC_HContext)&context, 0x0100007F);
EXPECT_EQ(std::strcmp(resultBuf, "127.0.0.1"), 0);
UDPC_atostr((UDPC_HContext)&context, 0x0201A8C0);
EXPECT_EQ(std::strcmp(context.atostrBuf, "192.168.1.2"), 0);
resultBuf = UDPC_atostr((UDPC_HContext)&context, 0xFF08000A);
EXPECT_EQ(std::strcmp(resultBuf, "10.0.8.255"), 0);
resultBuf = UDPC_atostr((UDPC_HContext)&context, 0x0201A8C0);
EXPECT_EQ(std::strcmp(resultBuf, "192.168.1.2"), 0);
}
TEST(UDPC, atostr_concurrent) {
UDPC::Context context(false);
const char* results[64] = {
"0.0.0.0",
"1.1.1.1",
"2.2.2.2",
"3.3.3.3",
"4.4.4.4",
"5.5.5.5",
"6.6.6.6",
"7.7.7.7",
"8.8.8.8",
"9.9.9.9",
"10.10.10.10",
"11.11.11.11",
"12.12.12.12",
"13.13.13.13",
"14.14.14.14",
"15.15.15.15",
"16.16.16.16",
"17.17.17.17",
"18.18.18.18",
"19.19.19.19",
"20.20.20.20",
"21.21.21.21",
"22.22.22.22",
"23.23.23.23",
"24.24.24.24",
"25.25.25.25",
"26.26.26.26",
"27.27.27.27",
"28.28.28.28",
"29.29.29.29",
"30.30.30.30",
"31.31.31.31",
"32.32.32.32",
"33.33.33.33",
"34.34.34.34",
"35.35.35.35",
"36.36.36.36",
"37.37.37.37",
"38.38.38.38",
"39.39.39.39",
"40.40.40.40",
"41.41.41.41",
"42.42.42.42",
"43.43.43.43",
"44.44.44.44",
"45.45.45.45",
"46.46.46.46",
"47.47.47.47",
"48.48.48.48",
"49.49.49.49",
"50.50.50.50",
"51.51.51.51",
"52.52.52.52",
"53.53.53.53",
"54.54.54.54",
"55.55.55.55",
"56.56.56.56",
"57.57.57.57",
"58.58.58.58",
"59.59.59.59",
"60.60.60.60",
"61.61.61.61",
"62.62.62.62",
"63.63.63.63"
};
std::future<void> futures[64];
const char* ptrs[64];
for(unsigned int i = 0; i < 2; ++i) {
for(unsigned int j = 0; j < 64; ++j) {
futures[j] = std::async(std::launch::async, [] (unsigned int id, const char** ptr, UDPC::Context* c) {
ptr[id] = UDPC_atostr((UDPC_HContext)c, id | (id << 8) | (id << 16) | (id << 24));
}, j, ptrs, &context);
}
for(unsigned int j = 0; j < 64; ++j) {
ASSERT_TRUE(futures[j].valid());
futures[j].wait();
}
for(unsigned int j = 0; j < 64; ++j) {
EXPECT_EQ(std::strcmp(ptrs[j], results[j]), 0);
}
}
}
TEST(UDPC, strtoa) {