From: Mathieu Desnoyers Date: Thu, 17 Sep 2015 16:21:05 +0000 (-0400) Subject: urcu/ref.h: implement urcu_ref_get_unless_zero() X-Git-Tag: v0.9.0~36 X-Git-Url: http://git.liburcu.org/?p=urcu.git;a=commitdiff_plain;h=cd21955a846566b3cd7ca77d58cd3d006f3c533a urcu/ref.h: implement urcu_ref_get_unless_zero() Allows getting a reference atomically if the reference count is not zero. Returns true if the reference is taken, false otherwise. This needs to be used in conjunction with another synchronization technique (e.g. RCU or mutex) to ensure existence of the reference count. Signed-off-by: Mathieu Desnoyers --- diff --git a/urcu/ref.h b/urcu/ref.h index a422a99..74be50d 100644 --- a/urcu/ref.h +++ b/urcu/ref.h @@ -15,6 +15,7 @@ */ #include +#include #include struct urcu_ref { @@ -45,4 +46,30 @@ static inline void urcu_ref_put(struct urcu_ref *ref, release(ref); } +/* + * urcu_ref_get_unless_zero + * + * Allows getting a reference atomically if the reference count is not + * zero. Returns true if the reference is taken, false otherwise. This + * needs to be used in conjunction with another synchronization + * technique (e.g. RCU or mutex) to ensure existence of the reference + * count. + */ +static inline bool urcu_ref_get_unless_zero(struct urcu_ref *ref) +{ + long old, _new, res; + + old = uatomic_read(&ref->refcount); + for (;;) { + if (old == 0) + return false; /* Failure. */ + _new = old + 1; + res = uatomic_cmpxchg(&ref->refcount, old, _new); + if (res == old) { + return true; /* Success. */ + } + old = res; + } +} + #endif /* _URCU_REF_H */