#ifndef AO_STACK_H
#define AO_STACK_H
#include "atomic_ops.h"
#ifdef __cplusplus
extern "C" {
#endif
#ifdef AO_USE_ALMOST_LOCK_FREE
#elif !defined(AO_HAVE_compare_double_and_swap_double) \
&& !defined(AO_HAVE_compare_double_and_swap) \
&& defined(AO_HAVE_compare_and_swap)
# define AO_USE_ALMOST_LOCK_FREE
#else
# define AO_STACK_IS_LOCK_FREE
#endif
#ifdef AO_USE_ALMOST_LOCK_FREE
# if defined(__LP64__) || defined(_LP64) || defined(_WIN64)
# define AO_N_BITS 3
# else
# define AO_N_BITS 2
# endif
# define AO_BIT_MASK ((1 << AO_N_BITS) - 1)
#ifndef AO_BL_SIZE
# define AO_BL_SIZE 2
#endif
#if AO_BL_SIZE > (1 << AO_N_BITS)
# error AO_BL_SIZE too big
#endif
typedef struct AO__stack_aux {
volatile AO_t AO_stack_bl[AO_BL_SIZE];
} AO_stack_aux;
#define AO_REAL_NEXT_PTR(x) (AO_t *)((x) & ~AO_BIT_MASK)
AO_API void
AO_stack_push_explicit_aux_release(volatile AO_t *list, AO_t *x,
AO_stack_aux *);
AO_API AO_t *
AO_stack_pop_explicit_aux_acquire(volatile AO_t *list, AO_stack_aux *);
typedef struct AO__stack {
volatile AO_t AO_ptr;
AO_stack_aux AO_aux;
} AO_stack_t;
#define AO_STACK_INITIALIZER {0,{{0}}}
AO_INLINE void AO_stack_init(AO_stack_t *list)
{
# if AO_BL_SIZE == 2
list -> AO_aux.AO_stack_bl[0] = 0;
list -> AO_aux.AO_stack_bl[1] = 0;
# else
int i;
for (i = 0; i < AO_BL_SIZE; ++i)
list -> AO_aux.AO_stack_bl[i] = 0;
# endif
list -> AO_ptr = 0;
}
#define AO_REAL_HEAD_PTR(x) AO_REAL_NEXT_PTR((x).AO_ptr)
#define AO_stack_push_release(l, e) \
AO_stack_push_explicit_aux_release(&((l)->AO_ptr), e, &((l)->AO_aux))
#define AO_HAVE_stack_push_release
#define AO_stack_pop_acquire(l) \
AO_stack_pop_explicit_aux_acquire(&((l)->AO_ptr), &((l)->AO_aux))
#define AO_HAVE_stack_pop_acquire
# else
#ifndef AO_HAVE_double_t
# ifdef __cplusplus
}
# endif
# include "atomic_ops/sysdeps/standard_ao_double_t.h"
# ifdef __cplusplus
extern "C" {
# endif
#endif
typedef volatile AO_double_t AO_stack_t;
#define AO_STACK_INITIALIZER AO_DOUBLE_T_INITIALIZER
AO_INLINE void AO_stack_init(AO_stack_t *list)
{
list -> AO_val1 = 0;
list -> AO_val2 = 0;
}
#define AO_REAL_HEAD_PTR(x) (AO_t *)((x).AO_val2)
#define AO_REAL_NEXT_PTR(x) (AO_t *)(x)
AO_API void AO_stack_push_release(AO_stack_t *list, AO_t *new_element);
#define AO_HAVE_stack_push_release
AO_API AO_t *AO_stack_pop_acquire(AO_stack_t *list);
#define AO_HAVE_stack_pop_acquire
#endif
#if defined(AO_HAVE_stack_push_release) && !defined(AO_HAVE_stack_push)
# define AO_stack_push(l, e) AO_stack_push_release(l, e)
# define AO_HAVE_stack_push
#endif
#if defined(AO_HAVE_stack_pop_acquire) && !defined(AO_HAVE_stack_pop)
# define AO_stack_pop(l) AO_stack_pop_acquire(l)
# define AO_HAVE_stack_pop
#endif
#ifdef __cplusplus
}
#endif
#endif