diff options
Diffstat (limited to 'src/mercury/mercury_thread_condition.h')
-rw-r--r-- | src/mercury/mercury_thread_condition.h | 182 |
1 files changed, 182 insertions, 0 deletions
diff --git a/src/mercury/mercury_thread_condition.h b/src/mercury/mercury_thread_condition.h new file mode 100644 index 0000000..70e9748 --- /dev/null +++ b/src/mercury/mercury_thread_condition.h @@ -0,0 +1,182 @@ +/* + * Copyright (C) 2013-2019 Argonne National Laboratory, Department of Energy, + * UChicago Argonne, LLC and The HDF Group. + * All rights reserved. + * + * The full copyright notice, including terms governing use, modification, + * and redistribution, is contained in the COPYING file that can be + * found at the root of the source code distribution tree. + */ + +#ifndef MERCURY_THREAD_CONDITION_H +#define MERCURY_THREAD_CONDITION_H + +#include "mercury_thread_mutex.h" + +#ifdef _WIN32 +typedef CONDITION_VARIABLE hg_thread_cond_t; +#else +# if defined(HG_UTIL_HAS_PTHREAD_CONDATTR_SETCLOCK) +# include "mercury_time.h" +# elif defined(HG_UTIL_HAS_SYSTIME_H) +# include <sys/time.h> +# endif +# include <stdlib.h> +typedef pthread_cond_t hg_thread_cond_t; +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Initialize the condition. + * + * \param cond [IN/OUT] pointer to condition object + * + * \return Non-negative on success or negative on failure + */ +HG_UTIL_PUBLIC int +hg_thread_cond_init(hg_thread_cond_t *cond); + +/** + * Destroy the condition. + * + * \param cond [IN/OUT] pointer to condition object + * + * \return Non-negative on success or negative on failure + */ +HG_UTIL_PUBLIC int +hg_thread_cond_destroy(hg_thread_cond_t *cond); + +/** + * Wake one thread waiting for the condition to change. + * + * \param cond [IN/OUT] pointer to condition object + * + * \return Non-negative on success or negative on failure + */ +static HG_UTIL_INLINE int +hg_thread_cond_signal(hg_thread_cond_t *cond); + +/** + * Wake all the threads waiting for the condition to change. + * + * \param cond [IN/OUT] pointer to condition object + * + * \return Non-negative on success or negative on failure + */ +static HG_UTIL_INLINE int +hg_thread_cond_broadcast(hg_thread_cond_t *cond); + +/** + * Wait for the condition to change. + * + * \param cond [IN/OUT] pointer to condition object + * \param mutex [IN/OUT] pointer to mutex object + * + * \return Non-negative on success or negative on failure + */ +static HG_UTIL_INLINE int +hg_thread_cond_wait(hg_thread_cond_t *cond, hg_thread_mutex_t *mutex); + +/** + * Wait timeout ms for the condition to change. + * + * \param cond [IN/OUT] pointer to condition object + * \param mutex [IN/OUT] pointer to mutex object + * \param timeout [IN] timeout (in milliseconds) + * + * \return Non-negative on success or negative on failure + */ +static HG_UTIL_INLINE int +hg_thread_cond_timedwait( + hg_thread_cond_t *cond, hg_thread_mutex_t *mutex, unsigned int timeout); + +/*---------------------------------------------------------------------------*/ +static HG_UTIL_INLINE int +hg_thread_cond_signal(hg_thread_cond_t *cond) +{ +#ifdef _WIN32 + WakeConditionVariable(cond); +#else + if (pthread_cond_signal(cond)) + return HG_UTIL_FAIL; +#endif + + return HG_UTIL_SUCCESS; +} + +/*---------------------------------------------------------------------------*/ +static HG_UTIL_INLINE int +hg_thread_cond_broadcast(hg_thread_cond_t *cond) +{ +#ifdef _WIN32 + WakeAllConditionVariable(cond); +#else + if (pthread_cond_broadcast(cond)) + return HG_UTIL_FAIL; +#endif + + return HG_UTIL_SUCCESS; +} + +/*---------------------------------------------------------------------------*/ +static HG_UTIL_INLINE int +hg_thread_cond_wait(hg_thread_cond_t *cond, hg_thread_mutex_t *mutex) +{ +#ifdef _WIN32 + if (!SleepConditionVariableCS(cond, mutex, INFINITE)) + return HG_UTIL_FAIL; +#else + if (pthread_cond_wait(cond, mutex)) + return HG_UTIL_FAIL; +#endif + + return HG_UTIL_SUCCESS; +} + +/*---------------------------------------------------------------------------*/ +static HG_UTIL_INLINE int +hg_thread_cond_timedwait( + hg_thread_cond_t *cond, hg_thread_mutex_t *mutex, unsigned int timeout) +{ +#ifdef _WIN32 + if (!SleepConditionVariableCS(cond, mutex, timeout)) + return HG_UTIL_FAIL; +#else +# if defined(HG_UTIL_HAS_PTHREAD_CONDATTR_SETCLOCK) + hg_time_t now; +# elif defined(HG_UTIL_HAS_SYSTIME_H) + struct timeval now; +# endif + struct timespec abs_timeout; + long int abs_timeout_us; + ldiv_t ld; + + /* Need to convert timeout (ms) to absolute time */ +# if defined(HG_UTIL_HAS_PTHREAD_CONDATTR_SETCLOCK) + if (hg_time_get_current(&now) != HG_UTIL_SUCCESS) + return HG_UTIL_FAIL; +# elif defined(HG_UTIL_HAS_SYSTIME_H) + if (gettimeofday(&now, NULL) != 0) + return HG_UTIL_FAIL; +# endif + abs_timeout_us = now.tv_usec + timeout * 1000L; + /* Get sec / nsec */ + ld = ldiv(abs_timeout_us, 1000000L); + abs_timeout.tv_sec = now.tv_sec + ld.quot; + abs_timeout.tv_nsec = ld.rem * 1000L; + + if (pthread_cond_timedwait(cond, mutex, &abs_timeout)) + return HG_UTIL_FAIL; +#endif + + return HG_UTIL_SUCCESS; +} + +#ifdef __cplusplus +} +#endif + +#endif /* MERCURY_THREAD_CONDITION_H */ |