diff options
author | David Lamparter <equinox@diac24.net> | 2019-06-21 10:58:02 +0200 |
---|---|---|
committer | David Lamparter <equinox@diac24.net> | 2019-09-03 17:15:17 +0200 |
commit | 00dffa8cde7661e00245ebe1b1eea248b8dd6802 (patch) | |
tree | a1e698d6b613b63407b3ad786565d09c7e7b7382 /lib/frr_pthread.h | |
parent | lib: add some macro helpers (diff) | |
download | frr-00dffa8cde7661e00245ebe1b1eea248b8dd6802.tar.xz frr-00dffa8cde7661e00245ebe1b1eea248b8dd6802.zip |
lib: add frr_with_mutex() block-wrapper
frr_with_mutex(...) { ... } locks and automatically unlocks the listed
mutex(es) when the block is exited. This adds a bit of safety against
forgetting the unlock in error paths & co. and makes the code a slight
bit more readable.
Signed-off-by: David Lamparter <equinox@opensourcerouting.org>
Diffstat (limited to 'lib/frr_pthread.h')
-rw-r--r-- | lib/frr_pthread.h | 48 |
1 files changed, 48 insertions, 0 deletions
diff --git a/lib/frr_pthread.h b/lib/frr_pthread.h index 6096a5037..f70c8a0db 100644 --- a/lib/frr_pthread.h +++ b/lib/frr_pthread.h @@ -215,6 +215,54 @@ void frr_pthread_stop_all(void); #define pthread_condattr_setclock(A, B) #endif +/* mutex auto-lock/unlock */ + +/* variant 1: + * (for short blocks, multiple mutexes supported) + * break & return can be used for aborting the block + * + * frr_with_mutex(&mtx, &mtx2) { + * if (error) + * break; + * ... + * } + */ +#define _frr_with_mutex(mutex) \ + *NAMECTR(_mtx_) __attribute__(( \ + unused, cleanup(_frr_mtx_unlock))) = _frr_mtx_lock(mutex), \ + /* end */ + +#define frr_with_mutex(...) \ + for (pthread_mutex_t MACRO_REPEAT(_frr_with_mutex, ##__VA_ARGS__) \ + *_once = NULL; _once == NULL; _once = (void *)1) \ + /* end */ + +/* variant 2: + * (more suitable for long blocks, no extra indentation) + * + * frr_mutex_lock_autounlock(&mtx); + * ... + */ +#define frr_mutex_lock_autounlock(mutex) \ + pthread_mutex_t *NAMECTR(_mtx_) \ + __attribute__((unused, cleanup(_frr_mtx_unlock))) = \ + _frr_mtx_lock(mutex) \ + /* end */ + +static inline pthread_mutex_t *_frr_mtx_lock(pthread_mutex_t *mutex) +{ + pthread_mutex_lock(mutex); + return mutex; +} + +static inline void _frr_mtx_unlock(pthread_mutex_t **mutex) +{ + if (!*mutex) + return; + pthread_mutex_unlock(*mutex); + *mutex = NULL; +} + #ifdef __cplusplus } #endif |