diff options
author | huisedenanhai <1728315644@qq.com> | 2019-09-04 00:04:37 +0800 |
---|---|---|
committer | huisedenanhai <1728315644@qq.com> | 2019-09-04 12:17:07 +0800 |
commit | 124e51fdde79e2130dd10ba75f92e9c727166e0b (patch) | |
tree | 6d16887828a1414a1df498ed4ecc60bac6198cba /core | |
parent | 5323d24fadadbc6c4a109a9848fd9c3ea08f4474 (diff) |
make core/Reference thread safe
Diffstat (limited to 'core')
-rw-r--r-- | core/reference.cpp | 18 | ||||
-rw-r--r-- | core/reference.h | 2 | ||||
-rw-r--r-- | core/safe_refcount.h | 9 |
3 files changed, 16 insertions, 13 deletions
diff --git a/core/reference.cpp b/core/reference.cpp index 1984af9a34..92bbdacd5d 100644 --- a/core/reference.cpp +++ b/core/reference.cpp @@ -36,12 +36,7 @@ bool Reference::init_ref() { if (reference()) { - // this may fail in the scenario of two threads assigning the pointer for the FIRST TIME - // at the same time, which is never likely to happen (would be crazy to do) - // so don't do it. - - if (refcount_init.get() > 0) { - refcount_init.unref(); + if (!is_referenced() && refcount_init.unref()) { unreference(); // first referencing is already 1, so compensate for the ref above } @@ -64,9 +59,11 @@ int Reference::reference_get_count() const { } bool Reference::reference() { - bool success = refcount.ref(); - if (success && refcount.get() <= 2 /* higher is not relevant */) { + uint32_t rc_val = refcount.refval(); + bool success = rc_val != 0; + + if (success && rc_val <= 2 /* higher is not relevant */) { if (get_script_instance()) { get_script_instance()->refcount_incremented(); } @@ -84,9 +81,10 @@ bool Reference::reference() { bool Reference::unreference() { - bool die = refcount.unref(); + uint32_t rc_val = refcount.unrefval(); + bool die = rc_val == 0; - if (refcount.get() <= 1 /* higher is not relevant */) { + if (rc_val <= 1 /* higher is not relevant */) { if (get_script_instance()) { bool script_ret = get_script_instance()->refcount_decremented(); die = die && script_ret; diff --git a/core/reference.h b/core/reference.h index 20ee22ddfc..b8d00a94ad 100644 --- a/core/reference.h +++ b/core/reference.h @@ -47,7 +47,7 @@ protected: static void _bind_methods(); public: - _FORCE_INLINE_ bool is_referenced() const { return refcount_init.get() < 1; } + _FORCE_INLINE_ bool is_referenced() const { return refcount_init.get() != 1; } bool init_ref(); bool reference(); // returns false if refcount is at zero and didn't get increased bool unreference(); diff --git a/core/safe_refcount.h b/core/safe_refcount.h index 54f540b0c7..47161eed57 100644 --- a/core/safe_refcount.h +++ b/core/safe_refcount.h @@ -177,12 +177,12 @@ struct SafeRefCount { public: // destroy() is called when weak_count_ drops to zero. - _ALWAYS_INLINE_ bool ref() { //true on success + _ALWAYS_INLINE_ bool ref() { // true on success return atomic_conditional_increment(&count) != 0; } - _ALWAYS_INLINE_ uint32_t refval() { //true on success + _ALWAYS_INLINE_ uint32_t refval() { // none-zero on success return atomic_conditional_increment(&count); } @@ -192,6 +192,11 @@ public: return atomic_decrement(&count) == 0; } + _ALWAYS_INLINE_ uint32_t unrefval() { // 0 if must be disposed of + + return atomic_decrement(&count); + } + _ALWAYS_INLINE_ uint32_t get() const { // nothrow return count; |