#ifndef AC_THREAD_H
#define AC_THREAD_H
#ifdef __cplusplus
extern "C"
{
#endif
#define AC_PRV_TLS_NODE_CACHE_MAX_DEPTH 5000
#define AC_PRV_TLS_LOCK_RECURSE_MAX_DEPTH 6
typedef void* ( AC_CDECL *ac_fp_thread_entry_t ) ( void* );
typedef struct ac_thread_cfg_
{
ac_flags_t flags;
} ac_thread_cfg_t;
typedef struct ac_thread_shared_recurse_
{
void *lock;
ac_intword_t count;
} ac_thread_shared_recurse_t;
#ifdef _MSC_VER
#pragma warning ( disable : 4324 )
#endif
typedef struct
AC_DECLSPEC_ALIGN_CACHE_LINE
ac_thread_shared_
{
ac_intword_t refs;
} ac_thread_shared_t;
struct
AC_DECLSPEC_ALIGN_CACHE_LINE
ac_thread_
{
ac_thread_shared_t shared;
ac_cpu_node_t *local_cache;
ac_intword_t cache_count;
ac_thread_shared_recurse_t recurse[AC_PRV_TLS_LOCK_RECURSE_MAX_DEPTH];
ac_intword_t recurse_index;
ac_cpu_node_t node;
ac_cpu_tls_t cpu_atomic;
ac_thread_cfg_t cfg;
ac_fp_thread_entry_t fp_entry;
const void *state;
ac_uintword_t id;
pthread_t thread;
void *this_mem;
};
#ifdef _MSC_VER
#pragma warning ( default : 4324 )
#endif
AC_APIEXPORT int AC_APIDECL
ac_thread_alloc
( ac_thread_t**,
ac_thread_cfg_t*,
ac_fp_thread_entry_t,
const void* );
AC_APIEXPORT int AC_APIDECL
ac_thread_join
( ac_thread_t*,
void** );
AC_APIEXPORT ac_thread_t* AC_APIDECL
ac_thread_self
( void );
AC_DECLSPEC_INLINE void AC_APIDECL
ac_sys_thread_recurse_locked
( ac_thread_t *_this,
void *lock )
{
ac_intword_t recurse = ++_this->recurse_index;
assert( ! _this->recurse[recurse].count );
_this->recurse[recurse].lock = lock;
}
AC_DECLSPEC_INLINE int AC_APIDECL
ac_sys_thread_recurse_inc
( ac_thread_t *_this,
void *lock )
{
ac_intword_t recurse = _this->recurse_index;
if ( recurse > -1 && _this->recurse[recurse].lock == lock )
{
++_this->recurse[recurse].count;
return 0;
}
return 1;
}
AC_DECLSPEC_INLINE int AC_APIDECL
ac_sys_thread_recurse_dec
( ac_thread_t *_this,
void *lock )
{
ac_intword_t recurse = _this->recurse_index,
count = _this->recurse[recurse].count;
if ( _this->recurse[recurse].lock != lock )
{
assert( _this->recurse[recurse].lock == lock );
return ac_sys_error( AC_ECORRUPTED );
}
if ( count )
{
_this->recurse[recurse].count = count - 1;
return 0;
}
_this->recurse_index = recurse - 1;
return 1;
}
AC_DECLSPEC_INLINE ac_cpu_node_t* AC_APIDECL
ac_thread_cpu_node_cache_pop
( ac_thread_t *_this,
const void *state )
{
ac_cpu_node_t *node = _this->local_cache;
if ( node )
{
--_this->cache_count;
_this->local_cache = node->next;
node->next = 0;
node->lfgc_next = 0;
node->state = state;
}
else
{
node = ac_cpu_node_cache_pop( state );
}
return node;
}
AC_DECLSPEC_INLINE void AC_APIDECL
ac_thread_cpu_node_cache_push
( ac_thread_t *_this,
ac_cpu_node_t *node )
{
if ( _this->cache_count < AC_PRV_TLS_NODE_CACHE_MAX_DEPTH )
{
++_this->cache_count;
node->next = _this->local_cache;
_this->local_cache = node;
}
else
{
ac_cpu_node_cache_push( node );
}
}
AC_DECLSPEC_INLINE int AC_APIDECL
ac_thread_cpu_node_cache_push_no_free
( ac_thread_t *_this,
ac_cpu_node_t *node )
{
if ( _this && node->fp_dtor == (ac_fp_dtor_t)0x00000001 )
{
++_this->cache_count;
node->next = _this->local_cache;
_this->local_cache = node;
}
else
{
return ac_cpu_node_cache_push_no_free( node );
}
return 0;
}
#ifdef __cplusplus
}
#endif
#endif