From 8be06cadb397466d55f90366373731e4fd6cf902 Mon Sep 17 00:00:00 2001 From: Patrick Pelissier Date: Wed, 20 May 2020 23:21:27 +0200 Subject: [PATCH] Add comments on description. --- m-core.h | 2 ++ m-mutex.h | 79 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ m-string.h | 1 + 3 files changed, 82 insertions(+) diff --git a/m-core.h b/m-core.h index fd7c9597..11c69b6b 100644 --- a/m-core.h +++ b/m-core.h @@ -1635,8 +1635,10 @@ M_PARSE_DEFAULT_TYPE_DEF(m_core_parse_ldouble, long double, strtold, ) NOTE: C definition is safer than the C++ one. */ #ifndef __cplusplus +/* Cast the object n into type only if it is C assignable */ # define M_ASSIGN_CAST(type, n) ((type) { 0 } = (n)) #else +/* Cast the object n into type using a static_cast */ # define M_ASSIGN_CAST(type, n) static_cast(n) #endif diff --git a/m-mutex.h b/m-mutex.h index 239b9264..2b5d6b64 100644 --- a/m-mutex.h +++ b/m-mutex.h @@ -35,63 +35,84 @@ #include #include "m-core.h" +/* Define a mutex type based on C11 definition */ typedef mtx_t m_mutex_t[1]; + +/* Define a condition variable type based on C11 definition */ typedef cnd_t m_cond_t[1]; + +/* Define a thread type based on C11 definition */ typedef thrd_t m_thread_t[1]; +/* Initialize the mutex (constructor) */ static inline void m_mutex_init(m_mutex_t m) { int rc = mtx_init(m, mtx_plain); + // Abort program in case of initialization failure + // There is really nothing else to do if a mutex cannot be constructed M_ASSERT_INIT (rc == 0, "mutex"); } +/* Clear the mutex (destructor) */ static inline void m_mutex_clear(m_mutex_t m) { mtx_destroy(m); } +/* Lock the mutex */ static inline void m_mutex_lock(m_mutex_t m) { mtx_lock(m); } +/* Unlock the mutex */ static inline void m_mutex_unlock(m_mutex_t m) { mtx_unlock(m); } +/* Initialize the condition variable (constructor) */ static inline void m_cond_init(m_cond_t c) { int rc = cnd_init(c); + // Abort program in case of initialization failure + // There is really nothing else to do if the object cannot be constructed M_ASSERT_INIT (rc == 0, "conditional variable"); } +/* Clear the condition variable (destructor) */ static inline void m_cond_clear(m_cond_t c) { cnd_destroy(c); } +/* Signal the condition variable to at least one waiting thread */ static inline void m_cond_signal(m_cond_t c) { cnd_signal(c); } +/* Signal the condition variable to all waiting threads */ static inline void m_cond_broadcast(m_cond_t c) { cnd_broadcast(c); } +/* Wait for signaling the condition variable by another thread */ static inline void m_cond_wait(m_cond_t c, m_mutex_t m) { cnd_wait(c, m); } +/* Create the thread (constructor) and start it */ static inline void m_thread_create(m_thread_t t, void (*func)(void*), void* arg) { int rc = thrd_create(t, (int(*)(void*))(void(*)(void))func, arg); + // Abort program in case of initialization failure M_ASSERT_INIT (rc == thrd_success, "thread"); } +/* Wait for the thread to terminate and destroy it (destructor) */ static inline void m_thread_join(m_thread_t t) { int rc = thrd_join(*t, NULL); @@ -100,11 +121,15 @@ static inline void m_thread_join(m_thread_t t) (void) rc; } +/* The thread has nothing meaningfull to do. + Inform the OS to let other threads be scheduled */ static inline void m_thread_yield(void) { thrd_yield(); } +/* Sleep the thread for at least usec microseconds. + Return true if the sleep was successful */ static inline bool m_thread_sleep(unsigned long long usec) { struct timespec tv; @@ -116,12 +141,17 @@ static inline bool m_thread_sleep(unsigned long long usec) // Internal type, not exported. typedef once_flag m_oncei_t[1]; + +// Initial value for m_oncei_t #define M_ONCEI_INIT_VALUE { ONCE_FLAG_INIT } + +// Call the function exactly once static inline void m_oncei_call(m_oncei_t o, void (*func)(void)) { call_once(o,func); } +// Attribute to use to allocate a global variable to a thread. #define M_THREAD_ATTR _Thread_local @@ -142,61 +172,77 @@ static inline void m_oncei_call(m_oncei_t o, void (*func)(void)) #include #include "m-core.h" +/* Define a thread type based on WINDOWS definition */ typedef HANDLE m_thread_t[1]; + +/* Define a mutex type based on WINDOWS definition */ typedef CRITICAL_SECTION m_mutex_t[1]; + +/* Define a condition variable type based on WINDOWS definition */ typedef CONDITION_VARIABLE m_cond_t[1]; +/* Initialize a mutex (Constructor)*/ static inline void m_mutex_init(m_mutex_t m) { InitializeCriticalSection(m); } +/* Clear a mutex (destructor) */ static inline void m_mutex_clear(m_mutex_t m) { DeleteCriticalSection(m); } +/* Lock a mutex */ static inline void m_mutex_lock(m_mutex_t m) { EnterCriticalSection(m); } +/* Unlock a mutex */ static inline void m_mutex_unlock(m_mutex_t m) { LeaveCriticalSection(m); } +/* Initialize a condition variable (constructor) */ static inline void m_cond_init(m_cond_t c) { InitializeConditionVariable(c); } +/* Clear a condition variable (destructor) */ static inline void m_cond_clear(m_cond_t c) { (void) c; // There is no destructor for this object. } +/* Signal a condition variable to at least one waiting thread */ static inline void m_cond_signal(m_cond_t c) { WakeConditionVariable(c); } +/* Signal a condition variable to all waiting threads */ static inline void m_cond_broadcast(m_cond_t c) { WakeAllConditionVariable(c); } +/* Wait for a condition variable */ static inline void m_cond_wait(m_cond_t c, m_mutex_t m) { SleepConditionVariableCS(c, m, INFINITE); } +/* Create a thread (constructor) and start it */ static inline void m_thread_create(m_thread_t t, void (*func)(void*), void *arg) { *t = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) (uintptr_t) func, arg, 0, NULL); M_ASSERT_INIT (*t != NULL, "thread"); } +/* Wait for the thread to terminate and destroy it (destructor) */ static inline void m_thread_join(m_thread_t t) { DWORD dwWaitResult = WaitForSingleObject(*t, INFINITE); @@ -205,11 +251,15 @@ static inline void m_thread_join(m_thread_t t) CloseHandle(*t); } +/* The thread has nothing meaningfull to do. + Inform the OS to let other threads be scheduled */ static inline void m_thread_yield(void) { Sleep(0); } +/* Sleep the thread for at least usec microseconds + Return true if the sleep was successful */ static inline bool m_thread_sleep(unsigned long long usec) { LARGE_INTEGER ft; @@ -241,8 +291,10 @@ static inline void m_oncei_call(m_oncei_t o, void (*func)(void)) } #if defined(_MSC_VER) +// Attribute to use to allocate a global variable to a thread (MSVC def). # define M_THREAD_ATTR __declspec( thread ) #else +// Attribute to use to allocate a global variable to a thread (GCC def). # define M_THREAD_ATTR __thread #endif @@ -261,69 +313,92 @@ static inline void m_oncei_call(m_oncei_t o, void (*func)(void)) #include #include "m-core.h" +/* Define a mutex type based on PTHREAD definition */ typedef pthread_mutex_t m_mutex_t[1]; + +/* Define a condition variable type based on PTHREAD definition */ typedef pthread_cond_t m_cond_t[1]; + +/* Define a thread type based on PTHREAD definition */ typedef pthread_t m_thread_t[1]; +/* Initialize the mutex (constructor) */ static inline void m_mutex_init(m_mutex_t m) { int _rc = pthread_mutex_init(m, NULL); + // Abort program in case of initialization failure + // There is really nothing else to do if a mutex cannot be constructed M_ASSERT_INIT (_rc == 0, "mutex"); } +/* Clear the mutex (destructor) */ static inline void m_mutex_clear(m_mutex_t m) { pthread_mutex_destroy(m); } +/* Lock the mutex */ static inline void m_mutex_lock(m_mutex_t m) { pthread_mutex_lock(m); } +/* Unlock the mutex */ static inline void m_mutex_unlock(m_mutex_t m) { pthread_mutex_unlock(m); } +/* Lazy lock initialization */ #define M_MUTEXI_INIT_VALUE { PTHREAD_MUTEX_INITIALIZER } + +/* Internal function compatible with lazy lock */ static inline void m_mutexi_lazy_lock(m_mutex_t m) { pthread_mutex_lock(m); } +/* Initialize the condition variable (constructor) */ static inline void m_cond_init(m_cond_t c) { int _rc = pthread_cond_init(c, NULL); + // Abort program in case of initialization failure + // There is really nothing else to do if a mutex cannot be constructed M_ASSERT_INIT (_rc == 0, "conditional variable"); } +/* Clear the condition variable (destructor) */ static inline void m_cond_clear(m_cond_t c) { pthread_cond_destroy(c); } +/* Signal a condition variable to at least a waiting thread */ static inline void m_cond_signal(m_cond_t c) { pthread_cond_signal(c); } +/* Signal a condition variable to all waiting threads */ static inline void m_cond_broadcast(m_cond_t c) { pthread_cond_broadcast(c); } +/* Waiting for a condition variable */ static inline void m_cond_wait(m_cond_t c, m_mutex_t m) { pthread_cond_wait(c, m); } +/* Create a thread (constructor) and start it */ static inline void m_thread_create(m_thread_t t, void (*func)(void*), void *arg) { int _rc = pthread_create(t, NULL, (void*(*)(void*))(void(*)(void))func, arg); M_ASSERT_INIT (_rc == 0, "thread"); } +/* Wait for the thread to terminate and destroy it (destructor) */ static inline void m_thread_join(m_thread_t t) { int _rc = pthread_join(*t, NULL); @@ -331,6 +406,8 @@ static inline void m_thread_join(m_thread_t t) assert (_rc == 0); } +/* The thread has nothing meaningfull to do. + Inform the OS to let other threads be scheduled */ static inline void m_thread_yield(void) { #ifdef _POSIX_PRIORITY_SCHEDULING @@ -338,6 +415,8 @@ static inline void m_thread_yield(void) #endif } +/* Sleep for at least usec microseconds + Return true if the sleep was successful */ static inline bool m_thread_sleep(unsigned long long usec) { struct timeval tv; diff --git a/m-string.h b/m-string.h index fae55ad7..1c9201de 100644 --- a/m-string.h +++ b/m-string.h @@ -1562,6 +1562,7 @@ string_utf8_p(string_t str) C++ definition. */ #ifndef __cplusplus +/* Initialize a constant string with the given C string */ # define STRING_CTE(s) \ ((const string_t){{.u.heap = { .size = sizeof(s)-1, .alloc = sizeof(s) } , \ .ptr = ((struct { long long _n; char _d[sizeof (s)]; }){ 0, s })._d }})