Rapicorn - Experimental UI Toolkit - Source Code
13.07.0
|
00001 // Licensed GNU LGPL v3 or later: http://www.gnu.org/licenses/lgpl.html 00002 #ifndef __RAPICORN_THREADLIB_HH__ 00003 #define __RAPICORN_THREADLIB_HH__ 00004 00005 #include <condition_variable> 00006 #include <rcore/cpuasm.hh> 00007 00008 namespace Rapicorn { 00009 namespace Lib { // Namespace for implementation internals 00010 00011 template<typename T> T atomic_load (T volatile *p) { RAPICORN_CFENCE; T t = *p; RAPICORN_LFENCE; return t; } 00012 template<typename T> void atomic_store (T volatile *p, T i) { RAPICORN_SFENCE; *p = i; RAPICORN_CFENCE; } 00013 00014 template<typename T> 00015 class Atomic { 00016 T volatile v; 00017 /*ctor*/ Atomic () = delete; 00018 /*ctor*/ Atomic (T&&) = delete; 00019 protected: 00020 constexpr Atomic (T i) : v (i) {} 00021 Atomic<T>& operator=(Atomic<T> &o) { store (o.load()); return *this; } 00022 Atomic<T> volatile& operator=(Atomic<T> &o) volatile { store (o.load()); return *this; } 00023 public: 00024 T load () const volatile { return atomic_load (&v); } 00025 void store (T i) volatile { atomic_store (&v, i); } 00026 bool cas (T o, T n) volatile { return __sync_bool_compare_and_swap (&v, o, n); } 00027 T operator+=(T i) volatile { return __sync_add_and_fetch (&v, i); } 00028 T operator-=(T i) volatile { return __sync_sub_and_fetch (&v, i); } 00029 T operator&=(T i) volatile { return __sync_and_and_fetch (&v, i); } 00030 T operator^=(T i) volatile { return __sync_xor_and_fetch (&v, i); } 00031 T operator|=(T i) volatile { return __sync_or_and_fetch (&v, i); } 00032 T operator++() volatile { return __sync_add_and_fetch (&v, 1); } 00033 T operator++(int) volatile { return __sync_fetch_and_add (&v, 1); } 00034 T operator--() volatile { return __sync_sub_and_fetch (&v, 1); } 00035 T operator--(int) volatile { return __sync_fetch_and_sub (&v, 1); } 00036 void operator= (T i) volatile { store (i); } 00037 operator T () const volatile { return load(); } 00038 }; 00039 00040 // == Once Scope == 00041 void once_list_enter (); 00042 bool once_list_bounce (volatile void *ptr); 00043 bool once_list_leave (volatile void *ptr); 00044 00045 class OnceScope { 00046 /*ctor*/ OnceScope (const OnceScope&) = delete; 00047 OnceScope& operator= (const OnceScope&) = delete; 00048 volatile char *volatile flagp; 00049 bool entered_once; 00050 public: 00051 OnceScope (volatile char *volatile p) : flagp (p), entered_once (false) {} 00052 inline bool 00053 operator() () 00054 { 00055 if (RAPICORN_LIKELY (*flagp != 0)) 00056 return false; 00057 if (entered_once > 0) // second or later invocation from for() 00058 { 00059 const bool is_first_initialization = __sync_bool_compare_and_swap (flagp, 0, 1); 00060 const bool found_and_removed = once_list_leave (flagp); 00061 if (!is_first_initialization || !found_and_removed) 00062 printerr ("__once: %s: assertion failed during leave: %d %d", __func__, is_first_initialization, found_and_removed); 00063 } 00064 entered_once = 1; // mark first invocation 00065 once_list_enter(); 00066 const bool initialized = atomic_load (flagp) != 0; 00067 const bool needs_init = once_list_bounce (initialized ? NULL : flagp); 00068 return needs_init; 00069 } 00070 }; 00071 00072 #define RAPICORN_ASECTION(bytes) __attribute__ ((section (".data.aligned" #bytes), aligned (bytes))) 00073 #define RAPICORN_DO_ONCE_COUNTER ({ static volatile char RAPICORN_ASECTION (1) __rapicorn_oncebyte_ = 0; &__rapicorn_oncebyte_; }) 00074 #define RAPICORN_DO_ONCE for (Rapicorn::Lib::OnceScope __rapicorn_oncescope_ (RAPICORN_DO_ONCE_COUNTER); __rapicorn_oncescope_(); ) 00075 00076 } // Lib 00077 } // Rapicorn 00078 00079 00080 #endif // __RAPICORN_THREADLIB_HH__