#ifndef AC_RWSPINLOCK_ALGO1_H
#define AC_RWSPINLOCK_ALGO1_H
#ifdef __cplusplus
extern "C"
{
#endif
#ifdef _MSC_VER
#pragma warning ( disable : 4324 )
#pragma pack(1)
#endif
typedef struct
AC_DECLSPEC_PACKED
ac_rwspinlock_algo1_shared_
{
ac_intword_t writes;
ac_intword_t reads;
} ac_rwspinlock_algo1_shared_t;
typedef struct
AC_DECLSPEC_PACKED_ALIGN_CACHE_LINE
ac_rwspinlock_algo1_shared_padded_
{
ac_rwspinlock_algo1_shared_t _this;
} ac_rwspinlock_algo1_shared_padded_t;
#ifdef _MSC_VER
#pragma pack()
#pragma warning ( default : 4324 )
#endif
typedef struct ac_rwspinlock_algo1_
{
ac_rwspinlock_algo1_shared_t *shared;
void *shared_mem;
} ac_rwspinlock_algo1_t;
AC_BUILD_DBG_ASSERT
( rwspinlock_algo1,
sizeof( ac_rwspinlock_algo1_shared_padded_t ) == AC_CPU_CACHE_LINE );
AC_APIEXPORT int AC_APIDECL
ac_rwspinlock_algo1_alloc
( ac_rwspinlock_algo1_t*,
ac_rwspinlock_algo1_shared_t* );
AC_APIEXPORT int AC_APIDECL
ac_rwspinlock_algo1_free
( ac_rwspinlock_algo1_t* );
AC_DECLSPEC_INLINE int AC_APIDECL
ac_rwspinlock_algo1_read_unlock
( ac_rwspinlock_algo1_t *_this,
ac_thread_t *_tls )
{
if ( ! _tls ) { _tls = ac_thread_self(); }
if ( ! ac_sys_thread_recurse_dec
( _tls,
_this ) )
{
return 0;
}
ac_atomic_dec_release( &_this->shared->reads );
return 0;
}
AC_DECLSPEC_INLINE int AC_APIDECL
ac_rwspinlock_algo1_write_unlock
( ac_rwspinlock_algo1_t *_this,
ac_thread_t *_tls )
{
if ( ! _tls ) { _tls = ac_thread_self(); }
if ( ! ac_sys_thread_recurse_dec
( _tls,
_this ) )
{
return 0;
}
ac_mb_store_release( &_this->shared->writes, 0 );
return 0;
}
AC_DECLSPEC_INLINE int AC_APIDECL
ac_rwspinlock_algo1_read_lock
( ac_rwspinlock_algo1_t *_this,
ac_thread_t *_tls )
{
if ( ! _tls ) { _tls = ac_thread_self(); }
if ( ! ac_sys_thread_recurse_inc
( _tls,
_this ) )
{
return 0;
}
for ( ;; )
{
while ( ac_mb_load_naked( &_this->shared->writes ) )
{
ac_cpu_pause_yield();
}
ac_atomic_inc_acquire( &_this->shared->reads );
if ( ! ac_mb_load_naked( &_this->shared->writes ) )
{
break;
}
ac_atomic_dec_release( &_this->shared->reads );
ac_cpu_pause_yield();
}
ac_sys_thread_recurse_locked
( _tls,
_this );
return 0;
}
AC_DECLSPEC_INLINE int AC_APIDECL
ac_rwspinlock_algo1_write_lock
( ac_rwspinlock_algo1_t *_this,
ac_thread_t *_tls )
{
if ( ! _tls ) { _tls = ac_thread_self(); }
if ( ! ac_sys_thread_recurse_inc
( _tls,
_this ) )
{
return 0;
}
while ( ac_atomic_xchg_acquire
( &_this->shared->writes, 1 ) )
{
ac_cpu_pause_yield();
}
while ( ac_mb_load_naked( &_this->shared->reads ) )
{
ac_cpu_pause_yield();
}
ac_sys_thread_recurse_locked
( _tls,
_this );
return 0;
}
#ifdef __cplusplus
}
#endif
#endif