summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIvan Maidanski <ivmai@mail.ru>2022-02-15 09:55:13 +0300
committerIvan Maidanski <ivmai@mail.ru>2022-02-15 14:57:57 +0300
commitd29c0910d85c5ca14c2f49a08ddc9149d23a6a88 (patch)
treebbf2d58b1b4038b3a5813ccc715154ca78907fb5
parentb2d599ba43ad12c2f631ad31c47d993ca208b0e1 (diff)
downloadlibatomic_ops-d29c0910d85c5ca14c2f49a08ddc9149d23a6a88.tar.gz
Do not expose AO_REAL_HEAD/NEXT_PTR implementation in header by default
Now AO_REAL_HEAD_PTR() and AO_REAL_NEXT_PTR() macros definition does not depend on whether the implementation is almost or fully lock-free. These macros just call the relevant implementation-dependent API function (AO_real_head_ptr or AO_real_next_ptr, respectively). If needed, the client could define AO_REAL_PTR_AS_MACRO (prior to include atomic_ops_stack.h) to continue using implementation-dependent definition of AO_REAL_HEAD_PTR and AO_REAL_NEXT_PTR macros. * src/atomic_ops_stack.c [!AO_REAL_PTR_AS_MACRO] (AO_REAL_PTR_AS_MACRO): Define (before include atomic_ops_stack.h). * src/atomic_ops_stack.c (AO_real_head_ptr, AO_real_next_ptr): Implement. * src/atomic_ops_stack.h [AO_USE_ALMOST_LOCK_FREE] (AO_stack_push_explicit_aux_release): Rename argument. * src/atomic_ops_stack.h [!AO_REAL_PTR_AS_MACRO] (AO_REAL_NEXT_PTR, AO_REAL_HEAD_PTR): Redirect to AO_real_next_ptr/AO_real_head_ptr(). * src/atomic_ops_stack.h (AO_stack_init): Move declaration down (to be after AO_stack_pop). * src/atomic_ops_stack.h (AO_real_head_ptr, AO_real_next_ptr): Declare AO_API function.
-rw-r--r--src/atomic_ops_stack.c14
-rw-r--r--src/atomic_ops_stack.h41
2 files changed, 37 insertions, 18 deletions
diff --git a/src/atomic_ops_stack.c b/src/atomic_ops_stack.c
index 0f23fdf..364f84c 100644
--- a/src/atomic_ops_stack.c
+++ b/src/atomic_ops_stack.c
@@ -23,6 +23,10 @@
# define AO_BUILD
#endif
+#ifndef AO_REAL_PTR_AS_MACRO
+# define AO_REAL_PTR_AS_MACRO
+#endif
+
#define AO_REQUIRE_CAS
#include "atomic_ops_stack.h"
@@ -31,6 +35,16 @@ AO_API void AO_stack_init(AO_stack_t *list)
memset((char *)list, 0, sizeof(list));
}
+AO_API AO_t *AO_real_head_ptr(const AO_stack_t *list)
+{
+ return AO_REAL_HEAD_PTR(*list);
+}
+
+AO_API AO_t *AO_real_next_ptr(AO_t next)
+{
+ return AO_REAL_NEXT_PTR(next);
+}
+
/* This function call must be a part of a do-while loop with a CAS */
/* designating the condition of the loop (see the use cases below). */
#ifdef AO_THREAD_SANITIZER
diff --git a/src/atomic_ops_stack.h b/src/atomic_ops_stack.h
index ef54d16..a1dc60d 100644
--- a/src/atomic_ops_stack.h
+++ b/src/atomic_ops_stack.h
@@ -122,38 +122,38 @@ typedef union AO__stack {
#define AO_STACK_INITIALIZER { /* .AO_pa= */ { 0, { {0} } } }
#ifdef AO_USE_ALMOST_LOCK_FREE
-
- /* The stack implementation knows only about the location of */
- /* link fields in nodes, and nothing about the rest of the */
- /* stack elements. Link fields hold an AO_t, which is not */
- /* necessarily a real pointer. This converts the AO_t to a */
- /* real (AO_t *) which is either NULL, or points at the link */
- /* field in the next node. */
-# define AO_REAL_NEXT_PTR(x) (AO_t *)((x) & ~AO_BIT_MASK)
-
/* The following two routines should not normally be used directly. */
/* We make them visible here for the rare cases in which it makes */
/* sense to share the AO_stack_aux between stacks. */
AO_API void
- AO_stack_push_explicit_aux_release(volatile AO_t *list, AO_t *x,
+ AO_stack_push_explicit_aux_release(volatile AO_t *list, AO_t *new_element,
AO_stack_aux *);
AO_API AO_t *
AO_stack_pop_explicit_aux_acquire(volatile AO_t *list, AO_stack_aux *);
+#endif /* AO_USE_ALMOST_LOCK_FREE */
+
+#ifndef AO_REAL_PTR_AS_MACRO
+ /* The stack implementation knows only about the location of */
+ /* link fields in nodes, and nothing about the rest of the */
+ /* stack elements. Link fields hold an AO_t, which is not */
+ /* necessarily a real pointer. This converts the AO_t to a */
+ /* real (AO_t *) which is either NULL, or points at the link */
+ /* field in the next node. */
+# define AO_REAL_NEXT_PTR(x) AO_real_next_ptr(x)
/* Convert an AO_stack_t to a pointer to the link field in */
/* the first element. */
-# define AO_REAL_HEAD_PTR(x) AO_REAL_NEXT_PTR((x).AO_pa.AO_ptr)
-
-#else /* Use fully non-blocking data structure, wide CAS. */
+# define AO_REAL_HEAD_PTR(x) AO_real_head_ptr(&(x))
-# define AO_REAL_HEAD_PTR(x) (AO_t *)((x).AO_vp.AO_val2)
+#elif defined(AO_USE_ALMOST_LOCK_FREE)
+# define AO_REAL_NEXT_PTR(x) (AO_t *)((x) & ~AO_BIT_MASK)
+# define AO_REAL_HEAD_PTR(x) AO_REAL_NEXT_PTR((x).AO_pa.AO_ptr)
+#else
# define AO_REAL_NEXT_PTR(x) (AO_t *)(x)
-
-#endif /* !AO_USE_ALMOST_LOCK_FREE */
-
-AO_API void AO_stack_init(AO_stack_t *list);
+# define AO_REAL_HEAD_PTR(x) (AO_t *)((x).AO_vp.AO_val2 /* ptr */)
+#endif /* AO_REAL_PTR_AS_MACRO && !AO_USE_ALMOST_LOCK_FREE */
AO_API void AO_stack_push_release(AO_stack_t *list, AO_t *new_element);
#define AO_HAVE_stack_push_release
@@ -167,6 +167,11 @@ AO_API AO_t *AO_stack_pop_acquire(AO_stack_t *list);
#define AO_stack_pop(l) AO_stack_pop_acquire(l)
#define AO_HAVE_stack_pop
+AO_API void AO_stack_init(AO_stack_t *list);
+
+AO_API AO_t *AO_real_head_ptr(const AO_stack_t *list);
+AO_API AO_t *AO_real_next_ptr(AO_t /* next */);
+
#ifdef __cplusplus
} /* extern "C" */
#endif