mirror of
https://github.com/citra-emu/citra.git
synced 2024-12-19 22:11:06 +00:00
kernel/object: Tighten object against data races
Despite being covered by a global mutex, we should still ensure that the class handles its reference counts properly. This avoids potential shenanigans when it comes to data races. Given this is the root object that drives quite a bit of the kernel object hierarchy, ensuring we always have the correct behavior (and no races) is a good thing.
This commit is contained in:
parent
05118a2326
commit
c47e1db46d
@ -14,7 +14,7 @@
|
|||||||
|
|
||||||
namespace Kernel {
|
namespace Kernel {
|
||||||
|
|
||||||
unsigned int Object::next_object_id;
|
std::atomic<u32> Object::next_object_id{0};
|
||||||
|
|
||||||
/// Initialize the kernel
|
/// Initialize the kernel
|
||||||
void Init(u32 system_mode) {
|
void Init(u32 system_mode) {
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <atomic>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
@ -48,8 +49,8 @@ public:
|
|||||||
virtual ~Object();
|
virtual ~Object();
|
||||||
|
|
||||||
/// Returns a unique identifier for the object. For debugging purposes only.
|
/// Returns a unique identifier for the object. For debugging purposes only.
|
||||||
unsigned int GetObjectId() const {
|
u32 GetObjectId() const {
|
||||||
return object_id;
|
return object_id.load(std::memory_order_relaxed);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual std::string GetTypeName() const {
|
virtual std::string GetTypeName() const {
|
||||||
@ -67,23 +68,23 @@ public:
|
|||||||
bool IsWaitable() const;
|
bool IsWaitable() const;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static unsigned int next_object_id;
|
static std::atomic<u32> next_object_id;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend void intrusive_ptr_add_ref(Object*);
|
friend void intrusive_ptr_add_ref(Object*);
|
||||||
friend void intrusive_ptr_release(Object*);
|
friend void intrusive_ptr_release(Object*);
|
||||||
|
|
||||||
unsigned int ref_count = 0;
|
std::atomic<u32> ref_count{0};
|
||||||
unsigned int object_id = next_object_id++;
|
std::atomic<u32> object_id{next_object_id++};
|
||||||
};
|
};
|
||||||
|
|
||||||
// Special functions used by boost::instrusive_ptr to do automatic ref-counting
|
// Special functions used by boost::instrusive_ptr to do automatic ref-counting
|
||||||
inline void intrusive_ptr_add_ref(Object* object) {
|
inline void intrusive_ptr_add_ref(Object* object) {
|
||||||
++object->ref_count;
|
object->ref_count.fetch_add(1, std::memory_order_relaxed);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void intrusive_ptr_release(Object* object) {
|
inline void intrusive_ptr_release(Object* object) {
|
||||||
if (--object->ref_count == 0) {
|
if (object->ref_count.fetch_sub(1, std::memory_order_acq_rel) == 1) {
|
||||||
delete object;
|
delete object;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user