urcu/ref.h: implement urcu_ref_get_unless_zero()
authorMathieu Desnoyers <mathieu.desnoyers@efficios.com>
Thu, 17 Sep 2015 16:21:05 +0000 (12:21 -0400)
committerMathieu Desnoyers <mathieu.desnoyers@efficios.com>
Thu, 17 Sep 2015 16:23:38 +0000 (12:23 -0400)
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 <mathieu.desnoyers@efficios.com>
urcu/ref.h

index a422a9906fd787d1482210a5a61b6f3611b7f99c..74be50d6bbe4e46d28603ba4cb8de3db2ed7794a 100644 (file)
@@ -15,6 +15,7 @@
  */
 
 #include <assert.h>
+#include <stdbool.h>
 #include <urcu/uatomic.h>
 
 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 */
This page took 0.026116 seconds and 4 git commands to generate.