Make refcounts atomic;
@@ -55,14 +55,34 @@ typedef struct {
extern const TypeInfo lovrTypeInfo[T_MAX];
+// If the thread module is enabled, we have to use atomic operations when modifying refcounts, which
+// are a bit slower and vary depending on the platform.
+#ifdef LOVR_ENABLE_THREAD
+ #ifdef _WIN32
+ #include <intrin.h>
+ #define Refcount int
+ #define refcount_increment(c) _InterlockedIncrement(&c)
+ #define refcount_decrement(c) _InterlockedDecrement(&c)
+ #else
+ #include <stdatomic.h>
+ #define Refcount _Atomic int
+ #define refcount_increment(c) (atomic_fetch_add(&c, 1) + 1)
+ #define refcount_decrement(c) (atomic_fetch_sub(&c, 1) - 1)
+ #endif
+#else
+ #define Refcount int
+ #define refcount_increment(c) ++c
+ #define refcount_decrement(c) --c
+#endif
+
typedef struct Ref {
Type type;
- int count;
+ Refcount count;
} Ref;
void* _lovrAlloc(size_t size, Type type);
#define _ref(o) ((Ref*) o - 1)
#define lovrAlloc(T) (T*) _lovrAlloc(sizeof(T), T_ ## T)
-#define lovrRetain(o) if (o && ++(_ref(o)->count) >= 0xff) lovrThrow("Ref count overflow")
-#define lovrRelease(T, o) if (o && --(_ref(o)->count) == 0) lovr ## T ## Destroy(o), free(_ref(o))
-#define lovrGenericRelease(o) if (o && --(_ref(o)->count) == 0) lovrTypeInfo[_ref(o)->type].destructor(o), free(_ref(o))
+#define lovrRetain(o) if (o && refcount_increment(_ref(o)->count) >= 0xfffffff) lovrThrow("Ref count overflow")
+#define lovrRelease(T, o) if (o && refcount_decrement(_ref(o)->count) == 0) lovr ## T ## Destroy(o), free(_ref(o))
+#define lovrGenericRelease(o) if (o && refcount_decrement(_ref(o)->count) == 0) lovrTypeInfo[_ref(o)->type].destructor(o), free(_ref(o))
