Prevent misuse of SafeRefCount

This commit is contained in:
Pedro J. Estébanez 2023-01-09 10:15:35 +01:00
parent 2a04b18d37
commit b1c7665866
2 changed files with 27 additions and 7 deletions

View file

@ -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)

View file

@ -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();
}