medfall

A super great game engine
Log | Files | Refs

platform_atomic.h (9534B)


      1 #pragma once
      2 
      3 #include "intrinsics.h"
      4 #include "platform.h"
      5 
      6 /*
      7  * non-relacy things
      8  */
      9 #if !PLATFORM_RELACY
     10 
     11 enum NonAtomicDollar { NONATOMIC_DOLLAR };
     12 #define $ NONATOMIC_DOLLAR
     13 
     14 template< typename T >
     15 struct NonAtomic {
     16 	T x;
     17 	T & operator()( NonAtomicDollar ) {
     18 		return x;
     19 	}
     20 };
     21 
     22 #define NONATOMIC( T ) NonAtomic< T >
     23 
     24 #endif
     25 
     26 /*
     27  * GCC/clang
     28  */
     29 #if !PLATFORM_RELACY && PLATFORM_GCCORCLANG
     30 
     31 struct atomic_s32 {
     32 	NONCOPYABLE( atomic_s32 );
     33 	atomic_s32() { store_relaxed( this, 0 ); }
     34 	atomic_s32( s32 x ) { store_relaxed( this, x ); }
     35 	s32 v;
     36 };
     37 
     38 struct atomic_s64 {
     39 	NONCOPYABLE( atomic_s64 );
     40 	atomic_s64() { store_relaxed( this, 0 ); }
     41 	atomic_s64( s64 x ) { store_relaxed( this, x ); }
     42 	s64 v;
     43 };
     44 
     45 struct atomic_u32 {
     46 	NONCOPYABLE( atomic_u32 );
     47 	atomic_u32() { store_relaxed( this, 0 ); }
     48 	atomic_u32( u32 x ) { store_relaxed( this, x ); }
     49 	u32 v;
     50 };
     51 
     52 struct atomic_u64 {
     53 	NONCOPYABLE( atomic_u64 );
     54 	atomic_u64() { store_relaxed( this, 0 ); }
     55 	atomic_u64( u64 x ) { store_relaxed( this, x ); }
     56 	u64 v;
     57 };
     58 
     59 #define load_relaxed( atom ) __atomic_load_n( &( atom )->v, __ATOMIC_RELAXED )
     60 #define store_relaxed( atom, x ) __atomic_store_n( &( atom )->v, ( x ), __ATOMIC_RELAXED )
     61 #define fetch_add_relaxed( atom, x ) __atomic_fetch_add( &( atom )->v, ( x ), __ATOMIC_RELAXED )
     62 #define fetch_sub_relaxed( atom, x ) __atomic_fetch_sub( &( atom )->v, ( x ), __ATOMIC_RELAXED )
     63 #define exchange_relaxed( atom, x ) __atomic_exchange_n( &( atom )->v, ( x ), __ATOMIC_RELAXED )
     64 #define compare_exchange_relaxed( atom, before, after ) __atomic_compare_exchange_n( &( atom )->v, ( before ), ( after ), false, __ATOMIC_RELAXED, __ATOMIC_RELAXED )
     65 
     66 #define load_acquire( atom ) __atomic_load_n( &( atom )->v, __ATOMIC_ACQUIRE )
     67 #define fetch_add_acquire( atom, x ) __atomic_fetch_add( &( atom )->v, ( x ), __ATOMIC_ACQUIRE )
     68 #define fetch_sub_acquire( atom, x ) __atomic_fetch_sub( &( atom )->v, ( x ), __ATOMIC_ACQUIRE )
     69 #define exchange_acquire( atom, x ) __atomic_exchange_n( &( atom )->v, ( x ), __ATOMIC_ACQUIRE )
     70 #define compare_exchange_acquire( atom, before, after ) __atomic_compare_exchange_n( &( atom )->v, ( before ), ( after ), false, __ATOMIC_ACQUIRE, __ATOMIC_ACQUIRE )
     71 
     72 #define store_release( atom, x ) __atomic_store_n( &( atom )->v, ( x ), __ATOMIC_RELEASE )
     73 #define fetch_add_release( atom, x ) __atomic_fetch_add( &( atom )->v, ( x ), __ATOMIC_RELEASE )
     74 #define fetch_sub_release( atom, x ) __atomic_fetch_sub( &( atom )->v, ( x ), __ATOMIC_RELEASE )
     75 #define exchange_release( atom, x ) __atomic_exchange_n( &( atom )->v, ( x ), __ATOMIC_RELEASE )
     76 #define compare_exchange_release( atom, before, after ) __atomic_compare_exchange_n( &( atom )->v, ( before ), ( after ), false, __ATOMIC_RELEASE, __ATOMIC_RELAXED )
     77 
     78 #define fetch_add_acqrel( atom, x ) __atomic_fetch_add( &( atom )->v, ( x ), __ATOMIC_ACQ_REL )
     79 #define fetch_sub_acqrel( atom, x ) __atomic_fetch_sub( &( atom )->v, ( x ), __ATOMIC_ACQ_REL )
     80 #define exchange_acqrel( atom, x ) __atomic_exchange_n( &( atom )->v, ( x ), __ATOMIC_ACQ_REL )
     81 #define compare_exchange_acqrel( atom, before, after ) __atomic_compare_exchange_n( &( atom )->v, ( before ), ( after ), false, __ATOMIC_ACQ_REL, __ATOMIC_ACQUIRE )
     82 
     83 #define load_seqcst( atom ) __atomic_load_n( &( atom )->v, __ATOMIC_SEQ_CST )
     84 #define store_seqcst( atom, x ) __atomic_store_n( &( atom )->v, ( x ), __ATOMIC_SEQ_CST )
     85 #define fetch_add_seqcst( atom, x ) __atomic_fetch_add( &( atom )->v, ( x ), __ATOMIC_SEQ_CST )
     86 #define fetch_sub_seqcst( atom, x ) __atomic_fetch_sub( &( atom )->v, ( x ), __ATOMIC_SEQ_CST )
     87 #define exchange_seqcst( atom, x ) __atomic_exchange_n( &( atom )->v, ( x ), __ATOMIC_SEQ_CST )
     88 #define compare_exchange_seqcst( atom, before, after ) __atomic_compare_exchange_n( &( atom )->v, ( before ), ( after ), false, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST )
     89 
     90 #endif
     91 
     92 /*
     93  * std::atomic
     94  */
     95 #if !PLATFORM_RELACY && !PLATFORM_GCCORCLANG
     96 
     97 #include <atomic>
     98 
     99 typedef std::atomic< s32 > atomic_s32;
    100 typedef std::atomic< s64 > atomic_s64;
    101 typedef std::atomic< u32 > atomic_u32;
    102 typedef std::atomic< u64 > atomic_u64;
    103 
    104 #define load_relaxed( atom ) ( atom )->load( std::memory_order_relaxed )
    105 #define store_relaxed( atom, x ) ( atom )->store( x, std::memory_order_relaxed )
    106 #define fetch_add_relaxed( atom, x ) ( atom )->fetch_add( x, std::memory_order_relaxed )
    107 #define fetch_sub_relaxed( atom, x ) ( atom )->fetch_sub( x, std::memory_order_relaxed )
    108 #define exchange_relaxed( atom, x ) ( atom )->exchange( x, std::memory_order_relaxed )
    109 #define compare_exchange_relaxed( atom, before, after ) ( atom )->compare_exchange_strong( *( before ), after, std::memory_order_relaxed, std::memory_order_relaxed )
    110 
    111 #define load_acquire( atom ) ( atom )->load( std::memory_order_acquire )
    112 #define fetch_add_acquire( atom, x ) ( atom )->fetch_add( x, std::memory_order_acquire )
    113 #define fetch_sub_acquire( atom, x ) ( atom )->fetch_sub( x, std::memory_order_acquire )
    114 #define exchange_acquire( atom, x ) ( atom )->exchange( x, std::memory_order_acquire )
    115 #define compare_exchange_acquire( atom, before, after ) ( atom )->compare_exchange_strong( *( before ), after, std::memory_order_acquire, std::memory_order_acquire )
    116 
    117 #define store_release( atom, x ) ( atom )->store( x, std::memory_order_release )
    118 #define fetch_add_release( atom, x ) ( atom )->fetch_add( x, std::memory_order_release )
    119 #define fetch_sub_release( atom, x ) ( atom )->fetch_sub( x, std::memory_order_release )
    120 #define exchange_release( atom, x ) ( atom )->exchange( x, std::memory_order_release )
    121 #define compare_exchange_release( atom, before, after ) ( atom )->compare_exchange_strong( *( before ), after, std::memory_order_release, std::memory_order_relaxed )
    122 
    123 #define fetch_add_acqrel( atom, x ) ( atom )->fetch_add( x, std::memory_order_acq_rel )
    124 #define fetch_sub_acqrel( atom, x ) ( atom )->fetch_sub( x, std::memory_order_acq_rel )
    125 #define exchange_acqrel( atom, x ) ( atom )->exchange( x, std::memory_order_acq_rel )
    126 #define compare_exchange_acqrel( atom, before, after ) ( atom )->compare_exchange_strong( *( before ), after, std::memory_order_acq_rel, std::memory_order_acquire )
    127 
    128 #define load_seqcst( atom ) ( atom )->load( std::memory_order_seq_cst )
    129 #define store_seqcst( atom, x ) ( atom )->store( x, std::memory_order_seq_cst )
    130 #define fetch_add_seqcst( atom, x ) ( atom )->fetch_add( x, std::memory_order_seq_cst )
    131 #define fetch_sub_seqcst( atom, x ) ( atom )->fetch_sub( x, std::memory_order_seq_cst )
    132 #define exchange_seqcst( atom, x ) ( atom )->exchange( x, std::memory_order_seq_cst )
    133 #define compare_exchange_seqcst( atom, before, after ) ( atom )->compare_exchange_strong( *( before ), after, std::memory_order_seq_cst, std::memory_order_seq_cst )
    134 
    135 #endif
    136 
    137 /*
    138  * relacy
    139  */
    140 #if PLATFORM_RELACY
    141 
    142 #define NONATOMIC( T ) rl::var< T >
    143 #define ATOMIC_ASSERT( p ) RL_ASSERT( p )
    144 
    145 #define atomic_s32 rl::atomic< s32 >
    146 #define atomic_s64 rl::atomic< s64 >
    147 #define atomic_u32 rl::atomic< u32 >
    148 #define atomic_u64 rl::atomic< u64 >
    149 
    150 #define load_relaxed( atom ) ( atom )->load( rl::memory_order_relaxed )
    151 #define store_relaxed( atom, x ) ( atom )->store( x, rl::memory_order_relaxed )
    152 #define fetch_add_relaxed( atom, x ) ( atom )->fetch_add( x, rl::memory_order_relaxed )
    153 #define fetch_sub_relaxed( atom, x ) ( atom )->fetch_sub( x, rl::memory_order_relaxed )
    154 #define exchange_relaxed( atom, x ) ( atom )->exchange( x, rl::memory_order_relaxed )
    155 #define compare_exchange_relaxed( atom, before, after ) ( atom )->compare_exchange_strong( *( before ), after, rl::memory_order_relaxed, rl::memory_order_relaxed )
    156 
    157 #define load_acquire( atom ) ( atom )->load( rl::memory_order_acquire )
    158 #define fetch_add_acquire( atom, x ) ( atom )->fetch_add( x, rl::memory_order_acquire )
    159 #define fetch_sub_acquire( atom, x ) ( atom )->fetch_sub( x, rl::memory_order_acquire )
    160 #define exchange_acquire( atom, x ) ( atom )->exchange( x, rl::memory_order_acquire )
    161 #define compare_exchange_acquire( atom, before, after ) ( atom )->compare_exchange_strong( *( before ), after, rl::memory_order_acquire, rl::memory_order_acquire )
    162 
    163 #define store_release( atom, x ) ( atom )->store( x, rl::memory_order_release )
    164 #define fetch_add_release( atom, x ) ( atom )->fetch_add( x, rl::memory_order_release )
    165 #define fetch_sub_release( atom, x ) ( atom )->fetch_sub( x, rl::memory_order_release )
    166 #define exchange_release( atom, x ) ( atom )->exchange( x, rl::memory_order_release )
    167 #define compare_exchange_release( atom, before, after ) ( atom )->compare_exchange_strong( *( before ), after, rl::memory_order_release, rl::memory_order_relaxed )
    168 
    169 #define fetch_add_acqrel( atom, x ) ( atom )->fetch_add( x, rl::memory_order_acq_rel )
    170 #define fetch_sub_acqrel( atom, x ) ( atom )->fetch_sub( x, rl::memory_order_acq_rel )
    171 #define exchange_acqrel( atom, x ) ( atom )->exchange( x, rl::memory_order_acq_rel )
    172 #define compare_exchange_acqrel( atom, before, after ) ( atom )->compare_exchange_strong( *( before ), after, rl::memory_order_acq_rel, rl::memory_order_acquire )
    173 
    174 #define load_seqcst( atom ) ( atom )->load( rl::memory_order_seq_cst )
    175 #define store_seqcst( atom, x ) ( atom )->store( x, rl::memory_order_seq_cst )
    176 #define fetch_add_seqcst( atom, x ) ( atom )->fetch_add( x, rl::memory_order_seq_cst )
    177 #define fetch_sub_seqcst( atom, x ) ( atom )->fetch_sub( x, rl::memory_order_seq_cst )
    178 #define exchange_seqcst( atom, x ) ( atom )->exchange( x, rl::memory_order_seq_cst )
    179 #define compare_exchange_seqcst( atom, before, after ) ( atom )->compare_exchange_strong( *( before ), after, rl::memory_order_seq_cst, rl::memory_order_seq_cst )
    180 
    181 #endif