#ifndef AC_DLIST_H
#define AC_DLIST_H
#ifdef __cplusplus
extern "C"
{
#endif
#ifdef _MSC_VER
#pragma pack(1)
#endif
typedef struct
AC_DECLSPEC_PACKED
ac_dlist_node_
{
struct ac_dlist_node_ *next;
struct ac_dlist_node_ *prev;
} ac_dlist_node_t;
typedef struct
AC_DECLSPEC_PACKED
ac_dlist_
{
ac_dlist_node_t *front;
ac_dlist_node_t *back;
} ac_dlist_t;
#ifdef _MSC_VER
#pragma pack()
#endif
AC_BUILD_DBG_ASSERT
( dlist,
sizeof( ac_dlist_node_t ) == sizeof( ac_cpu_node_t ) / 2 &&
sizeof( ac_dlist_node_t ) == AC_CPU_WORD_SIZE * 2 &&
sizeof( ac_dlist_t ) == AC_CPU_WORD_SIZE * 2 );
AC_DECLSPEC_INLINE void AC_APIDECL
ac_dlist_init
( ac_dlist_t *_this )
{
_this->front = 0;
_this->back = 0;
}
#define ac_dlist_get_front( ac_macro_this ) \
( (ac_macro_this)->front )
#define ac_dlist_get_back( ac_macro_this ) \
( (ac_macro_this)->back )
#define ac_mb_dlist_get_front( ac_macro_this ) \
( (ac_dlist_node_t*)ac_mb_loadptr_depends( &(ac_macro_this)->front ) )
#define ac_mb_dlist_get_back( ac_macro_this ) \
( (ac_dlist_node_t*)ac_mb_loadptr_depends( &(ac_macro_this)->back ) )
#define ac_dlist_node_get_next( ac_macro_this ) \
( (ac_macro_this)->next )
#define ac_dlist_node_get_prev( ac_macro_this ) \
( (ac_macro_this)->prev )
#define ac_mb_dlist_node_get_next( ac_macro_this ) \
( (ac_dlist_node_t*)ac_mb_loadptr_depends( &(ac_macro_this)->next ) )
#define ac_mb_dlist_node_get_prev( ac_macro_this ) \
( (ac_dlist_node_t*)ac_mb_loadptr_depends( &(ac_macro_this)->prev ) )
AC_DECLSPEC_INLINE void AC_APIDECL
ac_dlist_pop
( ac_dlist_t *_this,
ac_dlist_node_t *node )
{
ac_dlist_node_t
*next = node->next,
*prev = node->prev;
assert( _this->front &&
_this->back );
if ( ! next && ! prev )
{
_this->front = 0;
_this->back = 0;
}
else if ( next && ! prev )
{
next->prev = 0;
_this->front = next;
}
else if ( ! next && prev )
{
prev->next = 0;
_this->back = prev;
}
else
{
next->prev = prev;
prev->next = next;
}
}
AC_DECLSPEC_INLINE void AC_APIDECL
ac_dlist_push_back
( ac_dlist_t *_this,
ac_dlist_node_t *node )
{
node->next = 0;
node->prev = 0;
if ( ! _this->front )
{
assert( ! _this->front &&
! _this->back );
_this->front = node;
_this->back = node;
}
else
{
node->prev = _this->back;
_this->back->next = node;
_this->back = node;
}
}
AC_DECLSPEC_INLINE ac_dlist_node_t* AC_APIDECL
ac_dlist_pop_front
( ac_dlist_t *_this )
{
ac_dlist_node_t *front = _this->front;
if ( front )
{
ac_dlist_pop( _this, front );
}
return front;
}
AC_DECLSPEC_INLINE ac_dlist_node_t* AC_APIDECL
ac_dlist_pop_back
( ac_dlist_t *_this )
{
ac_dlist_node_t *back = _this->back;
if ( back )
{
ac_dlist_pop( _this, back );
}
return back;
}
AC_DECLSPEC_INLINE void AC_APIDECL
ac_mb_dlist_pop
( ac_dlist_t *_this,
ac_dlist_node_t *node )
{
ac_dlist_node_t *next, *prev;
next = (ac_dlist_node_t*)ac_mb_loadptr_depends( &node->next );
prev = (ac_dlist_node_t*)ac_mb_loadptr_depends( &node->prev );
assert( _this->front &&
_this->back );
if ( ! next && ! prev )
{
ac_mb_storeptr_release( &_this->front, 0 );
ac_mb_storeptr_release( &_this->back, 0 );
}
else if ( next && ! prev )
{
ac_mb_storeptr_release( &next->prev, 0 );
ac_mb_storeptr_release( &_this->front, next );
}
else if ( ! next && prev )
{
ac_mb_storeptr_release( &prev->next, 0 );
ac_mb_storeptr_release( &_this->back, prev );
}
else
{
ac_mb_storeptr_release( &next->prev, prev );
ac_mb_storeptr_release( &prev->next, next );
}
}
AC_DECLSPEC_INLINE void AC_APIDECL
ac_mb_dlist_push_back
( ac_dlist_t *_this,
ac_dlist_node_t *node )
{
node->next = 0;
node->prev = 0;
if ( ! _this->front )
{
assert( ! _this->front &&
! _this->back );
ac_mb_storeptr_release( &_this->front, node );
ac_mb_storeptr_release( &_this->back, node );
}
else
{
ac_dlist_node_t *back =
(ac_dlist_node_t*)
ac_mb_loadptr_depends( &_this->back );
ac_mb_storeptr_release( &node->prev, back );
ac_mb_storeptr_release( &back->next, node );
ac_mb_storeptr_release( &_this->back, node );
}
}
AC_DECLSPEC_INLINE ac_dlist_node_t* AC_APIDECL
ac_mb_dlist_pop_front
( ac_dlist_t *_this )
{
ac_dlist_node_t *front =
(ac_dlist_node_t*)
ac_mb_loadptr_depends( &_this->front );
if ( front )
{
ac_mb_dlist_pop( _this, front );
}
return front;
}
AC_DECLSPEC_INLINE ac_dlist_node_t* AC_APIDECL
ac_mb_dlist_pop_back
( ac_dlist_t *_this )
{
ac_dlist_node_t *back =
(ac_dlist_node_t*)
ac_mb_loadptr_depends( &_this->back );
if ( back )
{
ac_mb_dlist_pop( _this, back );
}
return back;
}
#define ac_dlist_pop_cast( ac_macro_this, ac_macro_node ) \
( ac_dlist_pop \
( (ac_dlist_t*)(ac_macro_this), \
(ac_dlist_node_t*)(ac_macro_node) ) )
#define ac_dlist_pop_front_cast( ac_macro_this ) \
( (void*)ac_dlist_pop_front \
( (ac_dlist_t*)(ac_macro_this) ) )
#define ac_dlist_pop_back_cast( ac_macro_this ) \
( (void*)ac_dlist_pop_back \
( (ac_dlist_t*)(ac_macro_this) ) )
#define ac_dlist_push_back_cast( ac_macro_this, ac_macro_node ) \
( ac_dlist_push_back \
( (ac_dlist_t*)(ac_macro_this), \
(ac_dlist_node_t*)(ac_macro_node) ) )
#define ac_mb_dlist_pop_cast( ac_macro_this, ac_macro_node ) \
( ac_mb_dlist_pop \
( (ac_dlist_t*)(ac_macro_this), \
(ac_dlist_node_t*)(ac_macro_node) ) )
#define ac_mb_dlist_pop_front_cast( ac_macro_this ) \
( (void*)ac_mb_dlist_pop_front \
( (ac_dlist_t*)(ac_macro_this) ) )
#define ac_mb_dlist_pop_back_cast( ac_macro_this ) \
( (void*)ac_mb_dlist_pop_back \
( (ac_dlist_t*)(ac_macro_this) ) )
#define ac_mb_dlist_push_back_cast( ac_macro_this, ac_macro_node ) \
( ac_mb_dlist_push_back \
( (ac_dlist_t*)(ac_macro_this), \
(ac_dlist_node_t*)(ac_macro_node) ) )
#define ac_dlist_get_front_cast( ac_macro_this ) \
( (void*)ac_dlist_get_front( (ac_dlist_node_t*)(ac_macro_this) ) )
#define ac_dlist_get_back_cast( ac_macro_this ) \
( (void*)ac_dlist_get_back( (ac_dlist_node_t*)(ac_macro_this) ) )
#define ac_mb_dlist_get_front_cast( ac_macro_this ) \
( (void*)ac_mb_dlist_get_front( (ac_dlist_node_t*)(ac_macro_this) ) )
#define ac_mb_dlist_get_back_cast( ac_macro_this ) \
( (void*)ac_mb_dlist_get_back( (ac_dlist_node_t*)(ac_macro_this) ) )
#define ac_dlist_node_get_next_cast( ac_macro_this ) \
( (void*)ac_dlist_node_get_next( (ac_dlist_node_t*)(ac_macro_this) ) )
#define ac_dlist_node_get_prev_cast( ac_macro_this ) \
( (void*)ac_dlist_node_get_prev( (ac_dlist_node_t*)(ac_macro_this) ) )
#define ac_mb_dlist_node_get_next_cast( ac_macro_this ) \
( (void*)ac_mb_dlist_node_get_next( (ac_dlist_node_t*)(ac_macro_this) ) )
#define ac_mb_dlist_node_get_prev_cast( ac_macro_this ) \
( (void*)ac_mb_dlist_node_get_prev( (ac_dlist_node_t*)(ac_macro_this) ) )
#ifdef __cplusplus
}
#endif
#endif