#include "../../../include/ac_eventcount_algo1.h"
#ifndef AC_I686_STACK_MPMC_H
#define AC_I686_STACK_MPMC_H
#ifdef __cplusplus
extern "C"
{
#endif
#ifdef _MSC_VER
#pragma warning ( disable : 4324 )
#pragma pack(1)
#endif
typedef struct
AC_DECLSPEC_PACKED
ac_i686_prv_stack_mpmc_shared_
{
ac_eventcount_algo1_shared_t wset;
ac_i686_stack_mpmc_t queue;
} ac_i686_prv_stack_mpmc_shared_t;
typedef struct
AC_DECLSPEC_PACKED_ALIGN_CACHE_LINE
ac_i686_prv_stack_mpmc_shared_padded_
{
ac_i686_prv_stack_mpmc_shared_t _this;
} ac_i686_prv_stack_mpmc_shared_padded_t;
#ifdef _MSC_VER
#pragma pack()
#pragma warning ( default : 4324 )
#endif
typedef struct ac_i686_prv_stack_mpmc_
{
ac_i686_prv_stack_mpmc_shared_t *shared;
ac_eventcount_algo1_t wset;
void *shared_mem;
} ac_i686_prv_stack_mpmc_t;
AC_BUILD_DBG_ASSERT
( i686_prv_stack_mpmc,
sizeof( ac_i686_prv_stack_mpmc_shared_padded_t ) == AC_CPU_CACHE_LINE );
AC_APIEXPORT int AC_APIDECL
ac_i686_prv_stack_mpmc_alloc
( ac_i686_prv_stack_mpmc_t*,
ac_i686_prv_stack_mpmc_shared_t* );
AC_APIEXPORT int AC_APIDECL
ac_i686_prv_stack_mpmc_free
( ac_i686_prv_stack_mpmc_t* );
AC_APIEXPORT ac_i686_node_t* AC_APIDECL
ac_i686_prv_stack_mpmc_timedpop
( ac_i686_prv_stack_mpmc_t*,
ac_thread_t*,
ac_lfgc_smr_hazard_t,
ac_timeout_t );
AC_DECLSPEC_INLINE int AC_APIDECL
ac_i686_prv_stack_mpmc_push
( ac_i686_prv_stack_mpmc_t *_this,
ac_thread_t *_tls,
const void *state )
{
int ret;
ac_i686_node_t *node;
if ( ! _tls ) { _tls = ac_thread_self(); };
node = ac_thread_cpu_node_cache_pop
( _tls,
state );
if (node) {
ac_i686_stack_mpmc_push_cas
( &_this->shared->queue,
node );
ret = ac_eventcount_algo1_signal_naked
( &_this->wset );
if ( ret ) { return ac_sys_error( ret ); }
return 0;
}
return ac_sys_error(ENOMEM);
}
AC_DECLSPEC_INLINE int AC_APIDECL
ac_i686_stack_mpmc_timedpop
( ac_i686_prv_stack_mpmc_t *_this,
ac_thread_t *_tls,
void **state,
ac_timeout_t timeout )
{
ac_i686_node_t *node;
ac_lfgc_smr_hazard_t hazard;
if ( ! _tls ) { _tls = ac_thread_self(); };
hazard = ac_lfgc_smr_get( _tls, 0 );
node = np_ac_i686_lfgc_smr_stack_mpmc_pop_dwcas
( &_this->shared->queue,
hazard );
if ( ! node )
{
node = ac_i686_prv_stack_mpmc_timedpop
( _this,
_tls,
hazard,
timeout );
if ( ! node ) { return ac_sys_error( ETIMEDOUT ); }
}
*state = (void*)node->state;
if ( ac_thread_cpu_node_cache_push_no_free
( _tls,
node ) )
{
ac_lfgc_smr_collect( _tls, 0, node );
}
return 0;
}
#define ac_i686_prv_stack_mpmc_pop( ac_macro_this, ac_macro_thread, ac_macro_state ) \
( ac_i686_stack_mpmc_timedpop \
( (ac_macro_this), \
(ac_macro_thread), \
(ac_macro_state), \
AC_INFINITE ) )
typedef ac_i686_prv_stack_mpmc_shared_t ac_stack_mpmc_shared_t;
typedef ac_i686_prv_stack_mpmc_shared_padded_t ac_stack_mpmc_shared_padded_t;
typedef ac_i686_prv_stack_mpmc_t ac_stack_mpmc_t;
#define ac_stack_mpmc_alloc ac_i686_prv_stack_mpmc_alloc
#define ac_stack_mpmc_free ac_i686_prv_stack_mpmc_free
#define ac_stack_mpmc_push ac_i686_prv_stack_mpmc_push
#define ac_stack_mpmc_timedpop ac_i686_stack_mpmc_timedpop
#define ac_stack_mpmc_pop ac_i686_prv_stack_mpmc_pop
#ifdef __cplusplus
}
#endif
#endif