Browse Source

update hatomic

ithewei 5 years ago
parent
commit
cc79c07f21
8 changed files with 163 additions and 41 deletions
  1. 2 0
      Makefile
  2. 58 20
      base/hatomic.h
  3. 10 10
      base/hbase.c
  4. 3 3
      base/hbase.h
  5. 7 8
      docs/apis.md
  6. 5 0
      unittest/CMakeLists.txt
  7. 39 0
      unittest/hatomic_test.c
  8. 39 0
      unittest/hatomic_test.cpp

+ 2 - 0
Makefile

@@ -93,6 +93,8 @@ unittest: prepare
 	$(CC)  -g -Wall -std=c99   -I. -Ibase            -o bin/mkdir_p           unittest/mkdir_test.c         base/hbase.c
 	$(CC)  -g -Wall -std=c99   -I. -Ibase            -o bin/rmdir_p           unittest/rmdir_test.c         base/hbase.c
 	$(CC)  -g -Wall -std=c99   -I. -Ibase            -o bin/date              unittest/date_test.c          base/htime.c
+	$(CC)  -g -Wall -std=c99   -I. -Ibase            -o bin/hatomic_test      unittest/hatomic_test.c       -pthread
+	$(CXX) -g -Wall -std=c++11 -I. -Ibase            -o bin/hatomic_cpp_test  unittest/hatomic_test.cpp     -pthread
 	$(CC)  -g -Wall -std=c99   -I. -Ibase            -o bin/hmutex_test       unittest/hmutex_test.c        base/htime.c -pthread
 	$(CC)  -g -Wall -std=c99   -I. -Ibase            -o bin/connect_test      unittest/connect_test.c       base/hsocket.c base/htime.c
 	$(CC)  -g -Wall -std=c99   -I. -Ibase            -o bin/socketpair_test   unittest/socketpair_test.c    base/hsocket.c

+ 58 - 20
base/hatomic.h

@@ -6,6 +6,12 @@
 // c++11
 #include <atomic>
 
+using std::atomic_flag;
+using std::atomic_long;
+
+#define ATOMIC_FLAG_TEST_AND_SET(p)     ((p)->test_and_set())
+#define ATOMIC_FLAG_CLEAR(p)            ((p)->clear())
+
 #else
 
 #include "hconfig.h"    // for HAVE_STDATOMIC_H
@@ -14,6 +20,13 @@
 // c11
 #include <stdatomic.h>
 
+#define ATOMIC_FLAG_TEST_AND_SET    atomic_flag_test_and_set
+#define ATOMIC_FLAG_CLEAR           atomic_flag_clear
+#define ATOMIC_ADD                  atomic_fetch_add
+#define ATOMIC_SUB                  atomic_fetch_sub
+#define ATOMIC_INC(p)               ATOMIC_ADD(p, 1)
+#define ATOMIC_DEC(p)               ATOMIC_SUB(p, 1)
+
 #else
 
 #include "hplatform.h"  // for bool, size_t
@@ -33,56 +46,81 @@ typedef volatile size_t             atomic_size_t;
 
 typedef struct atomic_flag { atomic_bool _Value; } atomic_flag;
 
-#define ATOMIC_FLAG_INIT        { 0 }
-#define ATOMIC_VAR_INIT(value)  (value)
+#ifdef _WIN32
+
+#define ATOMIC_ADD          InterlockedAdd
+#define ATOMIC_SUB(p, n)    InterlockedAdd(p, -n)
+#define ATOMIC_INC          InterlockedIncrement
+#define ATOMIC_DEC          InterlockedDecrement
 
-#ifdef __GNUC__
+#elif defined(__GNUC__)
 
+#define ATOMIC_FLAG_TEST_AND_SET    atomic_flag_test_and_set
 static inline bool atomic_flag_test_and_set(atomic_flag* p) {
     return !__sync_bool_compare_and_swap(&p->_Value, 0, 1);
 }
 
-static inline void atomic_flag_clear(atomic_flag* p) {
-    p->_Value = 0;
-}
+#define ATOMIC_ADD          __sync_fetch_and_add
+#define ATOMIC_SUB          __sync_fetch_and_sub
+#define ATOMIC_INC(p)       ATOMIC_ADD(p, 1)
+#define ATOMIC_DEC(p)       ATOMIC_SUB(p, 1)
+
+#endif
 
-#define atomic_fetch_add    __sync_fetch_and_add
-#define atomic_fetch_sub    __sync_fetch_add_sub
+#endif // HAVE_STDATOMIC_H
 
-#else
+#endif // __cplusplus
+
+#ifndef ATOMIC_FLAG_INIT
+#define ATOMIC_FLAG_INIT        { 0 }
+#endif
+
+#ifndef ATOMIC_VAR_INIT
+#define ATOMIC_VAR_INIT(value)  (value)
+#endif
 
+#ifndef ATOMIC_FLAG_TEST_AND_SET
+#define ATOMIC_FLAG_TEST_AND_SET    atomic_flag_test_and_set
 static inline bool atomic_flag_test_and_set(atomic_flag* p) {
     bool ret = p->_Value;
     p->_Value = 1;
     return ret;
 }
+#endif
 
+#ifndef ATOMIC_FLAG_CLEAR
+#define ATOMIC_FLAG_CLEAR           atomic_flag_clear
 static inline void atomic_flag_clear(atomic_flag* p) {
     p->_Value = 0;
 }
-
-#define atomic_fetch_add(p, n)  *(p); *(p) += (n)
-#define atomic_fetch_sub(p, n)  *(p); *(p) -= (n)
-
-#endif // __GNUC__
-#endif // HAVE_STDATOMIC_H
+#endif
 
 #ifndef ATOMIC_ADD
-#define ATOMIC_ADD      atomic_fetch_add
+#define ATOMIC_ADD(p, n)    (*(p) += (n))
 #endif
 
 #ifndef ATOMIC_SUB
-#define ATOMIC_SUB      atomic_fetch_sub
+#define ATOMIC_SUB(p, n)    (*(p) -= (n))
 #endif
 
 #ifndef ATOMIC_INC
-#define ATOMIC_INC(p)   ATOMIC_ADD(p, 1)
+#define ATOMIC_INC(p)       ((*(p))++)
 #endif
 
 #ifndef ATOMIC_DEC
-#define ATOMIC_DEC(p)   ATOMIC_SUB(p, 1)
+#define ATOMIC_DEC(p)       ((*(p))--)
 #endif
 
-#endif // __cplusplus
+typedef atomic_flag                 hatomic_flag_t;
+#define HATOMIC_FLAG_INIT           ATOMIC_FLAG_INIT
+#define hatomic_flag_test_and_set   ATOMIC_FLAG_TEST_AND_SET
+#define hatomic_flag_clear          ATOMIC_FLAG_CLEAR
+
+typedef atomic_long                 hatomic_t;
+#define HATOMIC_VAR_INIT            ATOMIC_VAR_INIT
+#define hatomic_add                 ATOMIC_ADD
+#define hatomic_sub                 ATOMIC_SUB
+#define hatomic_inc                 ATOMIC_INC
+#define hatomic_dec                 ATOMIC_DEC
 
 #endif // HV_ATOMIC_H_

+ 10 - 10
base/hbase.c

@@ -6,19 +6,19 @@
 
 #include "hatomic.h"
 
-static atomic_uint s_alloc_cnt = 0;
-static atomic_uint s_free_cnt = 0;
+static hatomic_t s_alloc_cnt = HATOMIC_VAR_INIT(0);
+static hatomic_t s_free_cnt = HATOMIC_VAR_INIT(0);
 
-unsigned int hv_alloc_cnt() {
+long hv_alloc_cnt() {
     return s_alloc_cnt;
 }
 
-unsigned int hv_free_cnt() {
+long hv_free_cnt() {
     return s_free_cnt;
 }
 
 void* safe_malloc(size_t size) {
-    ATOMIC_INC(&s_alloc_cnt);
+    hatomic_inc(&s_alloc_cnt);
     void* ptr = malloc(size);
     if (!ptr) {
         fprintf(stderr, "malloc failed!\n");
@@ -28,8 +28,8 @@ void* safe_malloc(size_t size) {
 }
 
 void* safe_realloc(void* oldptr, size_t newsize, size_t oldsize) {
-    ATOMIC_INC(&s_alloc_cnt);
-    ATOMIC_INC(&s_free_cnt);
+    hatomic_inc(&s_alloc_cnt);
+    hatomic_inc(&s_free_cnt);
     void* ptr = realloc(oldptr, newsize);
     if (!ptr) {
         fprintf(stderr, "realloc failed!\n");
@@ -42,7 +42,7 @@ void* safe_realloc(void* oldptr, size_t newsize, size_t oldsize) {
 }
 
 void* safe_calloc(size_t nmemb, size_t size) {
-    ATOMIC_INC(&s_alloc_cnt);
+    hatomic_inc(&s_alloc_cnt);
     void* ptr =  calloc(nmemb, size);
     if (!ptr) {
         fprintf(stderr, "calloc failed!\n");
@@ -52,7 +52,7 @@ void* safe_calloc(size_t nmemb, size_t size) {
 }
 
 void* safe_zalloc(size_t size) {
-    ATOMIC_INC(&s_alloc_cnt);
+    hatomic_inc(&s_alloc_cnt);
     void* ptr = malloc(size);
     if (!ptr) {
         fprintf(stderr, "malloc failed!\n");
@@ -66,7 +66,7 @@ void safe_free(void* ptr) {
     if (ptr) {
         free(ptr);
         ptr = NULL;
-        ATOMIC_INC(&s_free_cnt);
+        hatomic_inc(&s_free_cnt);
     }
 }
 

+ 3 - 3
base/hbase.h

@@ -28,10 +28,10 @@ HV_EXPORT void  safe_free(void* ptr);
         printd("free( %p )\tat [%s:%d:%s]\n", ptr, __FILE__, __LINE__, __FUNCTION__);\
     } while(0)
 
-HV_EXPORT unsigned int hv_alloc_cnt();
-HV_EXPORT unsigned int hv_free_cnt();
+HV_EXPORT long hv_alloc_cnt();
+HV_EXPORT long hv_free_cnt();
 static inline void hv_memcheck() {
-    printf("Memcheck => alloc:%u free:%u\n", hv_alloc_cnt(), hv_free_cnt());
+    printf("Memcheck => alloc:%ld free:%ld\n", hv_alloc_cnt(), hv_free_cnt());
 }
 #define HV_MEMCHECK    atexit(hv_memcheck);
 

+ 7 - 8
docs/apis.md

@@ -54,14 +54,13 @@
 - printd, printe
 
 ### hatomic.h
-- atomic_bool, atomic_char, atomic_short, atomic_int, atomic_long ...
-- atomic_flag
-- atomic_flag_test_and_set
-- atomic_flag_clear
-- atomic_fetch_add
-- atomic_fetch_sub
-- ATOMIC_ADD, ATOMIC_SUB
-- ATOMIC_INC, ATOMIC_DEC
+- hatomic_flag_t, hatomic_t
+- hatomic_flag_test_and_set
+- hatomic_flag_clear
+- hatomic_add
+- hatomic_sub
+- hatomic_inc
+- hatomic_dec
 
 ### herr.h
 - hv_strerror

+ 5 - 0
unittest/CMakeLists.txt

@@ -9,6 +9,10 @@ target_include_directories(rmdir_p PRIVATE .. ../base)
 add_executable(date date_test.c ../base/htime.c)
 target_include_directories(date PRIVATE .. ../base)
 
+add_executable(hatomic_test hatomic_test.c)
+target_include_directories(hatomic_test PRIVATE .. ../base)
+target_link_libraries(hatomic_test -lpthread)
+
 add_executable(hmutex_test hmutex_test.c ../base/htime.c)
 target_include_directories(hmutex_test PRIVATE .. ../base)
 target_link_libraries(hmutex_test -lpthread)
@@ -60,6 +64,7 @@ add_custom_target(unittest DEPENDS
     mkdir_p
     rmdir_p
     date
+    hatomic_test
     hmutex_test
     connect_test
     socketpair_test

+ 39 - 0
unittest/hatomic_test.c

@@ -0,0 +1,39 @@
+#include <stdio.h>
+
+#include "hatomic.h"
+#include "hthread.h"
+
+hatomic_flag_t flag = HATOMIC_FLAG_INIT;
+hatomic_t cnt = HATOMIC_VAR_INIT(0);
+
+HTHREAD_ROUTINE(test_hatomic_flag) {
+    if (!hatomic_flag_test_and_set(&flag)) {
+        printf("tid=%ld flag 0=>1\n", hv_gettid());
+    }
+    else {
+        printf("tid=%ld flag=1\n", hv_gettid());
+    }
+    return 0;
+}
+
+HTHREAD_ROUTINE(test_hatomic) {
+    for (int i = 0; i < 10; ++i) {
+        long n = hatomic_inc(&cnt);
+        printf("tid=%ld cnt=%ld\n", hv_gettid(), n);
+        hv_delay(1);
+    }
+    return 0;
+}
+
+int main() {
+    for (int i = 0; i < 10; ++i) {
+        hthread_create(test_hatomic_flag, NULL);
+    }
+
+    for (int i = 0; i < 10; ++i) {
+        hthread_create(test_hatomic, NULL);
+    }
+
+    hv_delay(1000);
+    return 0;
+}

+ 39 - 0
unittest/hatomic_test.cpp

@@ -0,0 +1,39 @@
+#include <stdio.h>
+
+#include "hatomic.h"
+#include "hthread.h"
+
+hatomic_flag_t flag = HATOMIC_FLAG_INIT;
+hatomic_t cnt = HATOMIC_VAR_INIT(0);
+
+HTHREAD_ROUTINE(test_hatomic_flag) {
+    if (!hatomic_flag_test_and_set(&flag)) {
+        printf("tid=%ld flag 0=>1\n", hv_gettid());
+    }
+    else {
+        printf("tid=%ld flag=1\n", hv_gettid());
+    }
+    return 0;
+}
+
+HTHREAD_ROUTINE(test_hatomic) {
+    for (int i = 0; i < 10; ++i) {
+        long n = hatomic_inc(&cnt);
+        printf("tid=%ld cnt=%ld\n", hv_gettid(), n);
+        hv_delay(1);
+    }
+    return 0;
+}
+
+int main() {
+    for (int i = 0; i < 10; ++i) {
+        hthread_create(test_hatomic_flag, NULL);
+    }
+
+    for (int i = 0; i < 10; ++i) {
+        hthread_create(test_hatomic, NULL);
+    }
+
+    hv_delay(1000);
+    return 0;
+}