#include "ac_eventcount_algo1.h"
#ifndef AC_QUEUE_SPSC_H
#define AC_QUEUE_SPSC_H
#ifdef __cplusplus
extern "C"
{
#endif
#ifdef _MSC_VER
#pragma warning ( disable : 4324 )
#pragma pack(1)
#endif
typedef struct
AC_DECLSPEC_PACKED
ac_queue_spsc_shared_
{
ac_cpu_queue_spsc_t queue;
ac_eventcount_algo1_shared_t impl_wset;
} ac_queue_spsc_shared_t;
typedef struct
AC_DECLSPEC_PACKED_ALIGN_CACHE_LINE
ac_queue_spsc_shared_padded_
{
ac_queue_spsc_shared_t _this;
} ac_queue_spsc_shared_padded_t;
#ifdef _MSC_VER
#pragma pack()
#pragma warning ( default : 4324 )
#endif
typedef struct ac_queue_spsc_
{
ac_queue_spsc_shared_t *shared;
ac_eventcount_algo1_t impl_wset;
void *shared_mem;
} ac_queue_spsc_t;
AC_BUILD_DBG_ASSERT
( queue_spsc,
sizeof( ac_queue_spsc_shared_padded_t ) == AC_CPU_CACHE_LINE );
AC_APIEXPORT int AC_APIDECL
ac_queue_spsc_alloc
( ac_queue_spsc_t*,
ac_queue_spsc_shared_t* );
AC_APIEXPORT int AC_APIDECL
ac_queue_spsc_free
( ac_queue_spsc_t* );
AC_APIEXPORT ac_cpu_node_t* AC_APIDECL
ac_prv_queue_spsc_timedpop
( ac_queue_spsc_t*,
ac_thread_t*,
ac_timeout_t );
#define ac_queue_spsc_pop( ac_macro_this, ac_macro_thread, ac_macro_state ) \
( ac_queue_spsc_timedpop \
( (ac_macro_this), \
(ac_macro_thread), \
(ac_macro_state), \
AC_INFINITE ) )
AC_DECLSPEC_INLINE ac_eventcount_algo1_t* AC_APIDECL
ac_queue_spsc_getec
( ac_queue_spsc_t *_this )
{
return &_this->impl_wset;
}
AC_DECLSPEC_INLINE int AC_APIDECL
ac_queue_spsc_push_nosig
( ac_queue_spsc_t *_this,
ac_thread_t *_tls,
const void *state )
{
ac_cpu_node_t *node;
if ( ! _tls ) { _tls = ac_thread_self(); };
node = ac_thread_cpu_node_cache_pop
( _tls,
state );
if (node) {
ac_cpu_queue_spsc_push
( &_this->shared->queue,
node );
return 0;
}
return ac_sys_error(ENOMEM);
}
AC_DECLSPEC_INLINE int AC_APIDECL
ac_queue_spsc_push
( ac_queue_spsc_t *_this,
ac_thread_t *_tls,
const void *state )
{
int ret;
ac_cpu_node_t *node;
if ( ! _tls ) { _tls = ac_thread_self(); };
node = ac_thread_cpu_node_cache_pop
( _tls,
state );
if (node) {
ac_cpu_queue_spsc_push
( &_this->shared->queue,
node );
ret = ac_eventcount_algo1_signal_fence
( &_this->impl_wset );
if ( ret ) { return ac_sys_error( ret ); }
return 0;
}
return ac_sys_error(ENOMEM);
}
AC_DECLSPEC_INLINE int AC_APIDECL
ac_queue_spsc_timedpop
( ac_queue_spsc_t *_this,
ac_thread_t *_tls,
void **state,
ac_timeout_t timeout )
{
ac_cpu_node_t *node;
if ( ! _tls ) { _tls = ac_thread_self(); };
node = ac_cpu_queue_spsc_pop( &_this->shared->queue );
if ( ! node )
{
node = ac_prv_queue_spsc_timedpop
( _this,
_tls,
timeout );
if ( ! node ) { return ac_sys_error( ETIMEDOUT ); }
}
*state = (void*)node->state;
ac_thread_cpu_node_cache_push
( _tls,
node );
return 0;
}
#ifdef __cplusplus
}
#endif
#endif