Browse Source

add hsem_t

ithewei 5 years ago
parent
commit
78f8b4c6b9
6 changed files with 146 additions and 55 deletions
  1. 77 6
      base/hmutex.h
  2. 43 0
      base/hplatform.h
  3. 2 37
      base/htime.h
  4. 1 0
      configure
  5. 4 0
      hconfig.h
  6. 19 12
      unittest/hmutex_test.c

+ 77 - 6
base/hmutex.h

@@ -54,6 +54,16 @@ static inline void honce(honce_t* once, honce_fn fn) {
     PVOID dummy = NULL;
     PVOID dummy = NULL;
     InitOnceExecuteOnce(once, s_once_func, (PVOID)fn, &dummy);
     InitOnceExecuteOnce(once, s_once_func, (PVOID)fn, &dummy);
 }
 }
+
+#define hsem_t                      HANDLE
+#define hsem_init(psem, value)      *(psem) = CreateSemaphore(NULL, value, value+100000, NULL)
+#define hsem_destroy(psem)          CloseHandle(*(psem))
+#define hsem_wait(psem)             WaitForSingleObject(*(psem), INFINITE)
+#define hsem_post(psem)             ReleaseSemaphore(*(psem))
+// true:  WAIT_OBJECT_0
+// false: WAIT_OBJECT_TIMEOUT
+#define hsem_wait_for(psem, ms)     ( WaitForSingleObject(*(psem), ms) == WAIT_OBJECT_0 )
+
 #else
 #else
 #define hmutex_t                pthread_mutex_t
 #define hmutex_t                pthread_mutex_t
 #define hmutex_init(pmutex)     pthread_mutex_init(pmutex, NULL)
 #define hmutex_init(pmutex)     pthread_mutex_init(pmutex, NULL)
@@ -67,6 +77,12 @@ static inline void honce(honce_t* once, honce_fn fn) {
 #define hspinlock_destroy       pthread_spin_destroy
 #define hspinlock_destroy       pthread_spin_destroy
 #define hspinlock_lock          pthread_spin_lock
 #define hspinlock_lock          pthread_spin_lock
 #define hspinlock_unlock        pthread_spin_unlock
 #define hspinlock_unlock        pthread_spin_unlock
+#else
+#define hspinlock_t             pthread_mutex_t
+#define hspinlock_init(pmutex)  pthread_mutex_init(pmutex, NULL)
+#define hspinlock_destroy       pthread_mutex_destroy
+#define hspinlock_lock          pthread_mutex_lock
+#define hspinlock_unlock        pthread_mutex_unlock
 #endif
 #endif
 
 
 #define hrwlock_t               pthread_rwlock_t
 #define hrwlock_t               pthread_rwlock_t
@@ -77,7 +93,6 @@ static inline void honce(honce_t* once, honce_fn fn) {
 #define hrwlock_wrlock          pthread_rwlock_wrlock
 #define hrwlock_wrlock          pthread_rwlock_wrlock
 #define hrwlock_wrunlock        pthread_rwlock_unlock
 #define hrwlock_wrunlock        pthread_rwlock_unlock
 
 
-#if HAVE_PTHREAD_MUTEX_TIMEDLOCK
 #define htimed_mutex_t              pthread_mutex_t
 #define htimed_mutex_t              pthread_mutex_t
 #define htimed_mutex_init(pmutex)   pthread_mutex_init(pmutex, NULL)
 #define htimed_mutex_init(pmutex)   pthread_mutex_init(pmutex, NULL)
 #define htimed_mutex_destroy        pthread_mutex_destroy
 #define htimed_mutex_destroy        pthread_mutex_destroy
@@ -85,7 +100,8 @@ static inline void honce(honce_t* once, honce_fn fn) {
 #define htimed_mutex_unlock         pthread_mutex_unlock
 #define htimed_mutex_unlock         pthread_mutex_unlock
 // true:  OK
 // true:  OK
 // false: ETIMEDOUT
 // false: ETIMEDOUT
-static inline int htimed_mutex_lock_for(htimed_mutex_t* mutex, unsigned long ms) {
+static inline int htimed_mutex_lock_for(htimed_mutex_t* mutex, unsigned int ms) {
+#if HAVE_PTHREAD_MUTEX_TIMEDLOCK
     struct timespec ts;
     struct timespec ts;
     struct timeval  tv;
     struct timeval  tv;
     gettimeofday(&tv, NULL);
     gettimeofday(&tv, NULL);
@@ -96,16 +112,28 @@ static inline int htimed_mutex_lock_for(htimed_mutex_t* mutex, unsigned long ms)
         ts.tv_sec += 1;
         ts.tv_sec += 1;
     }
     }
     return pthread_mutex_timedlock(mutex, &ts) != ETIMEDOUT;
     return pthread_mutex_timedlock(mutex, &ts) != ETIMEDOUT;
-}
+#else
+    int ret = 0;
+    unsigned int end = gettick() + ms;
+    while ((ret = pthread_mutex_trylock(mutex)) != 0) {
+        if (gettick() >= end) {
+            break;
+        }
+        msleep(1);
+    }
+    return ret == 0;
 #endif
 #endif
+}
 
 
 #define hcondvar_t              pthread_cond_t
 #define hcondvar_t              pthread_cond_t
 #define hcondvar_init(pcond)    pthread_cond_init(pcond, NULL)
 #define hcondvar_init(pcond)    pthread_cond_init(pcond, NULL)
 #define hcondvar_destroy        pthread_cond_destroy
 #define hcondvar_destroy        pthread_cond_destroy
 #define hcondvar_wait           pthread_cond_wait
 #define hcondvar_wait           pthread_cond_wait
+#define hcondvar_signal         pthread_cond_signal
+#define hcondvar_broadcast      pthread_cond_broadcast
 // true:  OK
 // true:  OK
 // false: ETIMEDOUT
 // false: ETIMEDOUT
-static inline int hcondvar_wait_for(hcondvar_t* cond, hmutex_t* mutex, unsigned long ms) {
+static inline int hcondvar_wait_for(hcondvar_t* cond, hmutex_t* mutex, unsigned int ms) {
     struct timespec ts;
     struct timespec ts;
     struct timeval  tv;
     struct timeval  tv;
     gettimeofday(&tv, NULL);
     gettimeofday(&tv, NULL);
@@ -117,12 +145,44 @@ static inline int hcondvar_wait_for(hcondvar_t* cond, hmutex_t* mutex, unsigned
     }
     }
     return pthread_cond_timedwait(cond, mutex, &ts) != ETIMEDOUT;
     return pthread_cond_timedwait(cond, mutex, &ts) != ETIMEDOUT;
 }
 }
-#define hcondvar_signal         pthread_cond_signal
-#define hcondvar_broadcast      pthread_cond_broadcast
 
 
 #define honce_t                 pthread_once_t
 #define honce_t                 pthread_once_t
 #define HONCE_INIT              PTHREAD_ONCE_INIT
 #define HONCE_INIT              PTHREAD_ONCE_INIT
 #define honce                   pthread_once
 #define honce                   pthread_once
+
+#include <semaphore.h>
+#define hsem_t                  sem_t
+#define hsem_init(psem, value)  sem_init(psem, 0, value)
+#define hsem_destroy            sem_destroy
+#define hsem_wait               sem_wait
+#define hsem_post               sem_post
+// true:  OK
+// false: ETIMEDOUT
+static inline int hsem_wait_for(hsem_t* sem, unsigned int ms) {
+#if HAVE_SEM_TIMEDWAIT
+    struct timespec ts;
+    struct timeval  tv;
+    gettimeofday(&tv, NULL);
+    ts.tv_sec = tv.tv_sec + ms / 1000;
+    ts.tv_nsec = tv.tv_usec * 1000 + ms % 1000 * 1000000;
+    if (ts.tv_nsec >= 1000000000) {
+        ts.tv_nsec -= 1000000000;
+        ts.tv_sec += 1;
+    }
+    return sem_timedwait(sem, &ts) != ETIMEDOUT;
+#else
+    int ret = 0;
+    unsigned int end = gettick() + ms;
+    while ((ret = sem_trywait(sem)) != 0) {
+        if (gettick() >= end) {
+            break;
+        }
+        msleep(1);
+    }
+    return ret == 0;
+#endif
+}
+
 #endif
 #endif
 
 
 #ifdef __cplusplus
 #ifdef __cplusplus
@@ -148,6 +208,17 @@ protected:
     hmutex_t _mutex;
     hmutex_t _mutex;
 };
 };
 
 
+class SpinLock {
+public:
+    SpinLock() { hspinlock_init(&_spin); }
+    ~SpinLock() { hspinlock_destroy(&_spin); }
+
+    void lock() { hspinlock_lock(&_spin); }
+    void unlock() { hspinlock_unlock(&_spin); }
+protected:
+    hspinlock_t _spin;
+};
+
 class RWLock {
 class RWLock {
 public:
 public:
     RWLock()    { hrwlock_init(&_rwlock); }
     RWLock()    { hrwlock_init(&_rwlock); }

+ 43 - 0
base/hplatform.h

@@ -204,4 +204,47 @@ typedef unsigned __int64    uint64_t;
 
 
 #endif
 #endif
 
 
+#ifdef OS_WIN
+static inline void sleep(unsigned int s) {
+    Sleep(s*1000);
+}
+
+static inline void usleep(unsigned int us) {
+    Sleep(us/1000);
+}
+#endif
+
+static inline void msleep(unsigned int ms) {
+#ifdef OS_WIN
+    Sleep(ms);
+#else
+    usleep(ms*1000);
+#endif
+}
+
+#if HAVE_CLOCK_GETTIME
+#ifndef CLOCK_REALTIME
+#define CLOCK_REALTIME 0
+#endif
+
+#ifndef CLOCK_MONOTONIC
+#define CLOCK_MONOTONIC 1
+#endif
+#endif
+
+// ms
+static inline unsigned int gettick() {
+#ifdef OS_WIN
+    return GetTickCount();
+#elif HAVE_CLOCK_GETTIME
+    struct timespec ts;
+    clock_gettime(CLOCK_MONOTONIC, &ts);
+    return ts.tv_sec * 1000 + ts.tv_nsec / 1000000;
+#else
+    struct timeval tv;
+    gettimeofday(&tv, NULL);
+    return tv.tv_sec * 1000 + tv.tv_usec / 1000;
+#endif
+}
+
 #endif // HV_PLATFORM_H_
 #endif // HV_PLATFORM_H_

+ 2 - 37
base/htime.h

@@ -26,14 +26,6 @@ typedef struct datetime_s {
 } datetime_t;
 } datetime_t;
 
 
 #ifdef OS_WIN
 #ifdef OS_WIN
-static inline void sleep(unsigned int s) {
-    Sleep(s*1000);
-}
-
-static inline void usleep(unsigned int us) {
-    Sleep(us/1000);
-}
-
 #ifdef _MSC_VER
 #ifdef _MSC_VER
 /* @see winsock2.h
 /* @see winsock2.h
 // Structure used in select() call, taken from the BSD file sys/time.h
 // Structure used in select() call, taken from the BSD file sys/time.h
@@ -51,56 +43,29 @@ struct timezone {
 #include <sys/timeb.h>
 #include <sys/timeb.h>
 static inline int gettimeofday(struct timeval *tv, struct timezone *tz) {
 static inline int gettimeofday(struct timeval *tv, struct timezone *tz) {
     struct _timeb tb;
     struct _timeb tb;
-
     _ftime(&tb);
     _ftime(&tb);
-
     if (tv) {
     if (tv) {
         tv->tv_sec =  (long)tb.time;
         tv->tv_sec =  (long)tb.time;
         tv->tv_usec = tb.millitm * 1000;
         tv->tv_usec = tb.millitm * 1000;
     }
     }
-
     if (tz) {
     if (tz) {
         tz->tz_minuteswest = tb.timezone;
         tz->tz_minuteswest = tb.timezone;
         tz->tz_dsttime = tb.dstflag;
         tz->tz_dsttime = tb.dstflag;
     }
     }
-
     return 0;
     return 0;
 }
 }
 #endif
 #endif
 #endif
 #endif
 
 
-static inline void msleep(unsigned int ms) {
-#ifdef OS_WIN
-    Sleep(ms);
-#else
-    usleep(ms*1000);
-#endif
-}
-
-// ms
-static inline unsigned int gettick() {
-#ifdef OS_WIN
-    return GetTickCount();
-#elif HAVE_CLOCK_GETTIME
-    struct timespec ts;
-    clock_gettime(CLOCK_MONOTONIC, &ts);
-    return ts.tv_sec * 1000 + ts.tv_nsec / 1000000;
-#else
+static inline unsigned long long timestamp_ms() {
     struct timeval tv;
     struct timeval tv;
     gettimeofday(&tv, NULL);
     gettimeofday(&tv, NULL);
-    return tv.tv_sec * 1000 + tv.tv_usec / 1000;
-#endif
+    return tv.tv_sec * (unsigned long long)1000 + tv.tv_usec/1000;
 }
 }
 
 
 // us
 // us
 unsigned long long gethrtime();
 unsigned long long gethrtime();
 
 
-static inline unsigned long long timestamp_ms() {
-    struct timeval tv;
-    gettimeofday(&tv, NULL);
-    return tv.tv_sec * (unsigned long long)1000 + tv.tv_usec/1000;
-}
-
 datetime_t datetime_now();
 datetime_t datetime_now();
 time_t     datetime_mktime(datetime_t* dt);
 time_t     datetime_mktime(datetime_t* dt);
 
 

+ 1 - 0
configure

@@ -125,6 +125,7 @@ function=clock_gettime && header=time.h && check_funtion
 function=gettimeofday && header=sys/time.h && check_funtion
 function=gettimeofday && header=sys/time.h && check_funtion
 function=pthread_spin_lock && header=pthread.h && check_funtion
 function=pthread_spin_lock && header=pthread.h && check_funtion
 function=pthread_mutex_timedlock && header=pthread.h && check_funtion
 function=pthread_mutex_timedlock && header=pthread.h && check_funtion
+function=sem_timedwait && header=semaphore.h && check_funtion
 
 
 # end confile
 # end confile
 cat << END >> $confile
 cat << END >> $confile

+ 4 - 0
hconfig.h

@@ -57,4 +57,8 @@
 #define HAVE_PTHREAD_MUTEX_TIMEDLOCK 0
 #define HAVE_PTHREAD_MUTEX_TIMEDLOCK 0
 #endif
 #endif
 
 
+#ifndef HAVE_SEM_TIMEDWAIT
+#define HAVE_SEM_TIMEDWAIT 0
+#endif
+
 #endif // HV_CONFIG_H_
 #endif // HV_CONFIG_H_

+ 19 - 12
unittest/hmutex_test.c

@@ -27,7 +27,6 @@ HTHREAD_ROUTINE(test_mutex) {
     return 0;
     return 0;
 }
 }
 
 
-#if HAVE_PTHREAD_SPIN_LOCK
 HTHREAD_ROUTINE(test_spinlock) {
 HTHREAD_ROUTINE(test_spinlock) {
     hspinlock_t spin;
     hspinlock_t spin;
     hspinlock_init(&spin);
     hspinlock_init(&spin);
@@ -37,7 +36,6 @@ HTHREAD_ROUTINE(test_spinlock) {
     printf("hspinlock test OK!\n");
     printf("hspinlock test OK!\n");
     return 0;
     return 0;
 }
 }
-#endif
 
 
 HTHREAD_ROUTINE(test_rwlock) {
 HTHREAD_ROUTINE(test_rwlock) {
     hrwlock_t rwlock;
     hrwlock_t rwlock;
@@ -51,7 +49,6 @@ HTHREAD_ROUTINE(test_rwlock) {
     return 0;
     return 0;
 }
 }
 
 
-#if HAVE_PTHREAD_MUTEX_TIMEDLOCK
 HTHREAD_ROUTINE(test_timed_mutex) {
 HTHREAD_ROUTINE(test_timed_mutex) {
     htimed_mutex_t mutex;
     htimed_mutex_t mutex;
     htimed_mutex_init(&mutex);
     htimed_mutex_init(&mutex);
@@ -65,7 +62,6 @@ HTHREAD_ROUTINE(test_timed_mutex) {
     printf("htimed_mutex test OK!\n");
     printf("htimed_mutex test OK!\n");
     return 0;
     return 0;
 }
 }
-#endif
 
 
 HTHREAD_ROUTINE(test_condvar) {
 HTHREAD_ROUTINE(test_condvar) {
     hmutex_t mutex;
     hmutex_t mutex;
@@ -88,28 +84,39 @@ HTHREAD_ROUTINE(test_condvar) {
     return 0;
     return 0;
 }
 }
 
 
+HTHREAD_ROUTINE(test_sem) {
+    hsem_t sem;
+    hsem_init(&sem, 10);
+    for (int i = 0; i < 10; ++i) {
+        hsem_wait(&sem);
+    }
+    hsem_post(&sem);
+    hsem_wait(&sem);
+    time_t start_time = time(NULL);
+    hsem_wait_for(&sem, 3000);
+    time_t end_time = time(NULL);
+    printf("hsem_wait_for %zds\n", end_time - start_time);
+    hsem_destroy(&sem);
+    printf("hsem test OK!\n");
+    return 0;
+}
+
 int main(int argc, char* argv[]) {
 int main(int argc, char* argv[]) {
     hthread_t thread_once = hthread_create(test_once, NULL);
     hthread_t thread_once = hthread_create(test_once, NULL);
     hthread_t thread_mutex = hthread_create(test_mutex, NULL);
     hthread_t thread_mutex = hthread_create(test_mutex, NULL);
-#if HAVE_PTHREAD_SPIN_LOCK
     hthread_t thread_spinlock = hthread_create(test_spinlock, NULL);
     hthread_t thread_spinlock = hthread_create(test_spinlock, NULL);
-#endif
     hthread_t thread_rwlock = hthread_create(test_rwlock, NULL);
     hthread_t thread_rwlock = hthread_create(test_rwlock, NULL);
-#if HAVE_PTHREAD_MUTEX_TIMEDLOCK
     hthread_t thread_timed_mutex = hthread_create(test_timed_mutex, NULL);
     hthread_t thread_timed_mutex = hthread_create(test_timed_mutex, NULL);
-#endif
     hthread_t thread_condvar = hthread_create(test_condvar, NULL);
     hthread_t thread_condvar = hthread_create(test_condvar, NULL);
+    hthread_t thread_sem = hthread_create(test_sem, NULL);
 
 
     hthread_join(thread_once);
     hthread_join(thread_once);
     hthread_join(thread_mutex);
     hthread_join(thread_mutex);
-#if HAVE_PTHREAD_SPIN_LOCK
     hthread_join(thread_spinlock);
     hthread_join(thread_spinlock);
-#endif
     hthread_join(thread_rwlock);
     hthread_join(thread_rwlock);
-#if HAVE_PTHREAD_MUTEX_TIMEDLOCK
     hthread_join(thread_timed_mutex);
     hthread_join(thread_timed_mutex);
-#endif
     hthread_join(thread_condvar);
     hthread_join(thread_condvar);
+    hthread_join(thread_sem);
     printf("hthread test OK!\n");
     printf("hthread test OK!\n");
     return 0;
     return 0;
 }
 }