]> git.seodisparate.com - UDPConnection/commitdiff
Make atostr more thread safe
authorStephen Seo <seo.disparate@gmail.com>
Tue, 3 Sep 2019 07:19:47 +0000 (16:19 +0900)
committerStephen Seo <seo.disparate@gmail.com>
Tue, 3 Sep 2019 07:19:47 +0000 (16:19 +0900)
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
cpp_impl/src/UDPConnection.cpp
cpp_impl/src/test/TestUDPC.cpp

index 40bfa7832a109a45124fed4259754bec117bb8a4..c65088cceb3573cd12f34b85249d6fe08f2082a5 100644 (file)
 #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;
index 4b924bd5359cb86c5a21c6b1e1f3875de45814fd..b0d51c9a63dd9fa0a012bea7fde21b595f98d311 100644 (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) {
index 77903aca8a3adf31d754e267a5eaed7ab338ceb5..bec109478d234e75e567196e42a38a47e852d009 100644 (file)
 #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) {