summaryrefslogtreecommitdiff
path: root/core
diff options
context:
space:
mode:
authorhuisedenanhai <1728315644@qq.com>2019-09-04 00:04:37 +0800
committerhuisedenanhai <1728315644@qq.com>2019-09-04 12:17:07 +0800
commit124e51fdde79e2130dd10ba75f92e9c727166e0b (patch)
tree6d16887828a1414a1df498ed4ecc60bac6198cba /core
parent5323d24fadadbc6c4a109a9848fd9c3ea08f4474 (diff)
make core/Reference thread safe
Diffstat (limited to 'core')
-rw-r--r--core/reference.cpp18
-rw-r--r--core/reference.h2
-rw-r--r--core/safe_refcount.h9
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;