123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211 |
- #ifndef SAFE_REFCOUNT_H
- #define SAFE_REFCOUNT_H
- #include "core/os/mutex.h"
- #include "core/typedefs.h"
- #include "platform_config.h"
- #ifdef NO_THREADS
- template <class T>
- static _ALWAYS_INLINE_ T atomic_conditional_increment(volatile T *pw) {
- if (*pw == 0)
- return 0;
- (*pw)++;
- return *pw;
- }
- template <class T>
- static _ALWAYS_INLINE_ T atomic_decrement(volatile T *pw) {
- (*pw)--;
- return *pw;
- }
- template <class T>
- static _ALWAYS_INLINE_ T atomic_increment(volatile T *pw) {
- (*pw)++;
- return *pw;
- }
- template <class T, class V>
- static _ALWAYS_INLINE_ T atomic_sub(volatile T *pw, volatile V val) {
- (*pw) -= val;
- return *pw;
- }
- template <class T, class V>
- static _ALWAYS_INLINE_ T atomic_add(volatile T *pw, volatile V val) {
- (*pw) += val;
- return *pw;
- }
- template <class T, class V>
- static _ALWAYS_INLINE_ T atomic_exchange_if_greater(volatile T *pw, volatile V val) {
- if (val > *pw)
- *pw = val;
- return *pw;
- }
- #elif defined(__GNUC__)
- template <class T>
- static _ALWAYS_INLINE_ T atomic_conditional_increment(volatile T *pw) {
- while (true) {
- T tmp = static_cast<T const volatile &>(*pw);
- if (tmp == 0)
- return 0;
- if (__sync_val_compare_and_swap(pw, tmp, tmp + 1) == tmp)
- return tmp + 1;
- }
- }
- template <class T>
- static _ALWAYS_INLINE_ T atomic_decrement(volatile T *pw) {
- return __sync_sub_and_fetch(pw, 1);
- }
- template <class T>
- static _ALWAYS_INLINE_ T atomic_increment(volatile T *pw) {
- return __sync_add_and_fetch(pw, 1);
- }
- template <class T, class V>
- static _ALWAYS_INLINE_ T atomic_sub(volatile T *pw, volatile V val) {
- return __sync_sub_and_fetch(pw, val);
- }
- template <class T, class V>
- static _ALWAYS_INLINE_ T atomic_add(volatile T *pw, volatile V val) {
- return __sync_add_and_fetch(pw, val);
- }
- template <class T, class V>
- static _ALWAYS_INLINE_ T atomic_exchange_if_greater(volatile T *pw, volatile V val) {
- while (true) {
- T tmp = static_cast<T const volatile &>(*pw);
- if (tmp >= val)
- return tmp;
- if (__sync_val_compare_and_swap(pw, tmp, val) == tmp)
- return val;
- }
- }
- #elif defined(_MSC_VER)
- uint32_t atomic_conditional_increment(volatile uint32_t *pw);
- uint32_t atomic_decrement(volatile uint32_t *pw);
- uint32_t atomic_increment(volatile uint32_t *pw);
- uint32_t atomic_sub(volatile uint32_t *pw, volatile uint32_t val);
- uint32_t atomic_add(volatile uint32_t *pw, volatile uint32_t val);
- uint32_t atomic_exchange_if_greater(volatile uint32_t *pw, volatile uint32_t val);
- uint64_t atomic_conditional_increment(volatile uint64_t *pw);
- uint64_t atomic_decrement(volatile uint64_t *pw);
- uint64_t atomic_increment(volatile uint64_t *pw);
- uint64_t atomic_sub(volatile uint64_t *pw, volatile uint64_t val);
- uint64_t atomic_add(volatile uint64_t *pw, volatile uint64_t val);
- uint64_t atomic_exchange_if_greater(volatile uint64_t *pw, volatile uint64_t val);
- #else
- #error Must provide atomic functions for this platform or compiler!
- #endif
- struct SafeRefCount {
- uint32_t count;
- public:
-
- _ALWAYS_INLINE_ bool ref() {
- return atomic_conditional_increment(&count) != 0;
- }
- _ALWAYS_INLINE_ uint32_t refval() {
- return atomic_conditional_increment(&count);
- }
- _ALWAYS_INLINE_ bool unref() {
- if (atomic_decrement(&count) == 0) {
- return true;
- }
- return false;
- }
- _ALWAYS_INLINE_ uint32_t get() const {
- return count;
- }
- _ALWAYS_INLINE_ void init(uint32_t p_value = 1) {
- count = p_value;
- }
- };
- #endif
|