Quellcode durchsuchen

make core/Reference thread safe

huisedenanhai vor 6 Jahren
Ursprung
Commit
124e51fdde
3 geänderte Dateien mit 16 neuen und 13 gelöschten Zeilen
  1. 8 10
      core/reference.cpp
  2. 1 1
      core/reference.h
  3. 7 2
      core/safe_refcount.h

+ 8 - 10
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;

+ 1 - 1
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();

+ 7 - 2
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;