#include "../include/sys/ac_sys.h"
#include "../include/ac_queue_spsc.h"
int AC_APIDECL
ac_queue_spsc_alloc
( ac_queue_spsc_t *_this,
ac_queue_spsc_shared_t *_shared )
{
int ret;
ac_cpu_node_t *dummy;
if ( ! _shared )
{
ac_queue_spsc_shared_padded_t *_padded;
_padded = ac_malloc_aligned
( &_this->shared_mem,
sizeof( *_padded ),
AC_CPU_CACHE_LINE );
if ( ! _padded ) { return ac_sys_error( ENOMEM ); }
_shared = &_padded->_this;
}
else { _this->shared_mem = 0; }
ret = AC_SYS_IS_MEM_ALIGNED
( _shared,
AC_CPU_WORD_SIZE );
if ( ret )
{
ac_free( _this->shared_mem );
return ac_sys_error( ret );
}
ret = ac_eventcount_algo1_alloc
( &_this->impl_wset,
&_shared->impl_wset );
if ( ret )
{
ac_free( _this->shared_mem );
return ac_sys_error( ret );
}
dummy = ac_malloc( sizeof( *_shared->queue.front ) );
if ( ! dummy )
{
ac_eventcount_algo1_free
( &_this->impl_wset );
ac_free( _this->shared_mem );
return ac_sys_error( ENOMEM );
}
ac_cpu_node_init( dummy, 0, 0 );
ac_i686_queue_spsc_init
( &_shared->queue,
dummy );
_this->shared = _shared;
return 0;
}
int AC_APIDECL
ac_queue_spsc_free
( ac_queue_spsc_t *_this )
{
int ret;
ac_thread_t *_tls = ac_thread_self();
if ( _this->shared->queue.front !=
_this->shared->queue.back )
{
return ac_sys_error( EBUSY );
}
ret = ac_eventcount_algo1_free
( &_this->impl_wset );
if ( ret ) { return ac_sys_error( ret ); }
ac_thread_cpu_node_cache_push
( _tls,
_this->shared->queue.front );
ac_free( _this->shared_mem );
return 0;
}
ac_cpu_node_t* AC_APIDECL
ac_prv_queue_spsc_timedpop
( ac_queue_spsc_t *_this,
ac_thread_t *_tls,
ac_timeout_t timeout )
{
ac_cpu_node_t *node;
ac_cpu_pause_yield();
node = ac_cpu_queue_spsc_pop
( &_this->shared->queue );
while ( ! node )
{
ac_eventcount_cmp_t cmp;
if ( ! timeout ) { return 0; }
cmp = ac_eventcount_algo1_get( &_this->impl_wset );
ac_cpu_pause_yield();
node = ac_cpu_queue_spsc_pop( &_this->shared->queue );
if ( ! node )
{
int ret = ac_eventcount_algo1_timedwait
( &_this->impl_wset,
_tls,
cmp,
timeout );
if ( ret ) { ac_sys_error( ret ); return 0; }
node = ac_cpu_queue_spsc_pop( &_this->shared->queue );
}
}
return node;
}