From 38eb06f105da0e447aff9597f727004e26aa89d5 Mon Sep 17 00:00:00 2001 From: Stephen Seo Date: Tue, 3 Sep 2019 16:19:47 +0900 Subject: [PATCH] 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. --- cpp_impl/src/UDPC_Defines.hpp | 7 ++- cpp_impl/src/UDPConnection.cpp | 7 ++- cpp_impl/src/test/TestUDPC.cpp | 103 +++++++++++++++++++++++++++++++-- 3 files changed, 108 insertions(+), 9 deletions(-) diff --git a/cpp_impl/src/UDPC_Defines.hpp b/cpp_impl/src/UDPC_Defines.hpp index 40bfa78..c65088c 100644 --- a/cpp_impl/src/UDPC_Defines.hpp +++ b/cpp_impl/src/UDPC_Defines.hpp @@ -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 #include #include @@ -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; diff --git a/cpp_impl/src/UDPConnection.cpp b/cpp_impl/src/UDPConnection.cpp index 4b924bd..b0d51c9 100644 --- a/cpp_impl/src/UDPConnection.cpp +++ b/cpp_impl/src/UDPConnection.cpp @@ -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) { diff --git a/cpp_impl/src/test/TestUDPC.cpp b/cpp_impl/src/test/TestUDPC.cpp index 77903ac..bec1094 100644 --- a/cpp_impl/src/test/TestUDPC.cpp +++ b/cpp_impl/src/test/TestUDPC.cpp @@ -4,18 +4,109 @@ #include #include +#include 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 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) {