41 |
# define LS_REF_ATOMIC 1 |
# define LS_REF_ATOMIC 1 |
42 |
#endif |
#endif |
43 |
|
|
44 |
//NOTE: We are using our own atomic implementation instead of std::atomic of the |
//NOTE: We are using our own atomic implementation for atomic increment and |
45 |
// C++ STL, because our atomic implementation is lock-free and wait-free. The |
// decrement instead of std::atomic of the C++ STL, because our atomic |
46 |
// C++ standard just recommends, but does not guarantee lock-free implementation |
// implementation is lock-free and wait-free. The C++ standard just recommends, |
47 |
// (state of the C++20 standard as of 2020-04-27): |
// but does not guarantee lock-free implementation (state of the C++20 standard |
48 |
|
// as of 2020-04-27): |
49 |
// https://en.cppreference.com/w/cpp/atomic/atomic/is_lock_free |
// https://en.cppreference.com/w/cpp/atomic/atomic/is_lock_free |
50 |
|
// For CAS though we simply use the STL version, since it is only used on |
51 |
|
// resource deallocation, which is not real-time safe anyway. |
52 |
#if LS_REF_ATOMIC |
#if LS_REF_ATOMIC |
53 |
# include "atomic.h" |
# include "atomic.h" |
54 |
# include <stdatomic.h> |
# include <atomic> |
|
# if __STDC_NO_ATOMICS__ |
|
|
# undef LS_REF_ATOMIC |
|
|
# warning Ref<> class will not be thread safe, since compiler does not support C11 atomics! |
|
|
# endif |
|
55 |
#else |
#else |
56 |
# warning Ref<> class will not be thread safe (feature explicitly disabled)! |
# warning Ref<> class will not be thread safe (feature explicitly disabled)! |
57 |
#endif |
#endif |
92 |
ptr(p) |
ptr(p) |
93 |
{ |
{ |
94 |
#if LS_REF_ATOMIC |
#if LS_REF_ATOMIC |
95 |
atomic_store(&zombi, released); |
std::atomic_store(&zombi, released); |
96 |
#endif |
#endif |
97 |
#if LS_REF_VERBOSE_DEBUG_MSG |
#if LS_REF_VERBOSE_DEBUG_MSG |
98 |
printf("Ref %p: new counter (refs=%d)\n", ptr, |
printf("Ref %p: new counter (refs=%d)\n", ptr, |
155 |
# endif |
# endif |
156 |
if (!zero) return; |
if (!zero) return; |
157 |
bool expect = false; |
bool expect = false; |
158 |
bool release = atomic_compare_exchange_strong(&zombi, &expect, true); |
bool release = std::atomic_compare_exchange_strong(&zombi, &expect, true); |
159 |
if (release) deletePtr(); |
if (release) deletePtr(); |
160 |
#else |
#else |
161 |
if (!references) return; |
if (!references) return; |
196 |
|
|
197 |
#if LS_REF_ATOMIC |
#if LS_REF_ATOMIC |
198 |
atomic_t references; |
atomic_t references; |
199 |
atomic_bool zombi; ///< @c false if not released yet, @c true once @c ptr was released |
std::atomic<bool> zombi; ///< @c false if not released yet, @c true once @c ptr was released |
200 |
#else |
#else |
201 |
int references; |
int references; |
202 |
#endif |
#endif |
298 |
public: |
public: |
299 |
typedef RefBase<T_BASE> RefBaseT; |
typedef RefBase<T_BASE> RefBaseT; |
300 |
typedef typename RefBase<T_BASE>::RefCounter RefCounter; |
typedef typename RefBase<T_BASE>::RefCounter RefCounter; |
301 |
|
|
302 |
Ref() : RefBaseT() { |
Ref() : RefBaseT() { |
303 |
#if LS_REF_VERBOSE_DEBUG_MSG |
#if LS_REF_VERBOSE_DEBUG_MSG |
304 |
printf("Ref empty ctor Ref:%p\n", this); |
printf("Ref empty ctor Ref:%p\n", this); |
378 |
inline operator RefBaseT&() { |
inline operator RefBaseT&() { |
379 |
return *this; |
return *this; |
380 |
} |
} |
381 |
|
|
382 |
inline operator const RefBaseT&() const { |
inline operator const RefBaseT&() const { |
383 |
return *this; |
return *this; |
384 |
} |
} |