summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPedro J. Estébanez <pedrojrulez@gmail.com>2023-01-09 10:15:35 +0100
committerPedro J. Estébanez <pedrojrulez@gmail.com>2023-01-09 10:17:55 +0100
commitb1c7665866717248a2d90ac8908acb9998da014a (patch)
treeab9fbfa2781de9ee088b6baaf930f4e68c4539f5
parent2a04b18d37de6c6e621db5a9dfd1cd0da5ccb015 (diff)
Prevent misuse of SafeRefCount
-rw-r--r--core/error/error_macros.h14
-rw-r--r--core/templates/safe_refcount.h20
2 files changed, 27 insertions, 7 deletions
diff --git a/core/error/error_macros.h b/core/error/error_macros.h
index 6901548cca..5f615d09cd 100644
--- a/core/error/error_macros.h
+++ b/core/error/error_macros.h
@@ -33,7 +33,7 @@
#include "core/typedefs.h"
-#include "core/templates/safe_refcount.h"
+#include <atomic> // We'd normally use safe_refcount.h, but that would cause circular includes.
class String;
@@ -737,10 +737,10 @@ void _err_flush_stdout();
*/
#define WARN_DEPRECATED \
if (true) { \
- static SafeFlag warning_shown; \
- if (!warning_shown.is_set()) { \
+ static std::atomic<bool> warning_shown; \
+ if (!warning_shown.load()) { \
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "This method has been deprecated and will be removed in the future.", false, ERR_HANDLER_WARNING); \
- warning_shown.set(); \
+ warning_shown.store(true); \
} \
} else \
((void)0)
@@ -750,10 +750,10 @@ void _err_flush_stdout();
*/
#define WARN_DEPRECATED_MSG(m_msg) \
if (true) { \
- static SafeFlag warning_shown; \
- if (!warning_shown.is_set()) { \
+ static std::atomic<bool> warning_shown; \
+ if (!warning_shown.load()) { \
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "This method has been deprecated and will be removed in the future.", m_msg, false, ERR_HANDLER_WARNING); \
- warning_shown.set(); \
+ warning_shown.store(true); \
} \
} else \
((void)0)
diff --git a/core/templates/safe_refcount.h b/core/templates/safe_refcount.h
index c4ffe5ca02..2599291a93 100644
--- a/core/templates/safe_refcount.h
+++ b/core/templates/safe_refcount.h
@@ -33,6 +33,10 @@
#include "core/typedefs.h"
+#ifdef DEV_ENABLED
+#include "core/error/error_macros.h"
+#endif
+
#include <atomic>
#include <type_traits>
@@ -163,6 +167,16 @@ public:
class SafeRefCount {
SafeNumeric<uint32_t> count;
+#ifdef DEV_ENABLED
+ _ALWAYS_INLINE_ void _check_unref_sanity() {
+ // This won't catch every misuse, but it's better than nothing.
+ CRASH_COND_MSG(count.get() == 0,
+ "Trying to unreference a SafeRefCount which is already zero is wrong and a symptom of it being misused.\n"
+ "Upon a SafeRefCount reaching zero any object whose lifetime is tied to it, as well as the ref count itself, must be destroyed.\n"
+ "Moreover, to guarantee that, no multiple threads should be racing to do the final unreferencing to zero.");
+ }
+#endif
+
public:
_ALWAYS_INLINE_ bool ref() { // true on success
return count.conditional_increment() != 0;
@@ -173,10 +187,16 @@ public:
}
_ALWAYS_INLINE_ bool unref() { // true if must be disposed of
+#ifdef DEV_ENABLED
+ _check_unref_sanity();
+#endif
return count.decrement() == 0;
}
_ALWAYS_INLINE_ uint32_t unrefval() { // 0 if must be disposed of
+#ifdef DEV_ENABLED
+ _check_unref_sanity();
+#endif
return count.decrement();
}