calling mono_gchandle_get_target instead of using expiring raw pointers

This commit is contained in:
Timerix 2025-04-21 21:16:07 +05:00
parent 5d84e744ce
commit 5c247ce032
2 changed files with 36 additions and 21 deletions

View File

@ -24,6 +24,8 @@ typedef f64 Double;
typedef union { mono_bool wide_bool; } Bool; //USAGE: Bool t = {true};
typedef char16_t Char;
typedef MonoString* String;
/// @warning MonoObject can be moved in memory by GC in any time and raw pointer will be invalid.
/// Use ObjectHandle where it is possible.
typedef MonoObject* Object;
typedef void Void;
@ -133,25 +135,39 @@ public:
std::shared_ptr<Assembly> loadAssembly(const std::string& name);
};
class ObjectHandle {
Object object;
/// @brief ObjectHandle can be used to store reliable reference to MonoObject.
/// MonoObject can be moved in memory by GC in any time and raw pointer will be invalid.
struct ObjectHandle {
u32 gc_handle;
public:
inline ObjectHandle() : object(nullptr), gc_handle(0) {}
inline ObjectHandle(Object obj) : object(obj) { gc_handle = mono_gchandle_new(obj, false); }
inline ObjectHandle() : gc_handle(0) {}
inline ObjectHandle(Object obj) {
gc_handle = mono_gchandle_new(obj, false);
}
/// implicitly create new ObjectHandle instead
inline ObjectHandle(const ObjectHandle& o) = delete;
inline ObjectHandle(ObjectHandle&& o)
: object(o.object), gc_handle(o.gc_handle)
{ o.gc_handle = 0; };
inline ObjectHandle(ObjectHandle&& o) {
gc_handle = o.gc_handle;
o.gc_handle = 0;
}
inline ObjectHandle& operator=(ObjectHandle&& o) {
object = o.object;
gc_handle = o.gc_handle;
o.gc_handle = 0;
return *this;
};
inline ~ObjectHandle() { if(gc_handle) mono_gchandle_free(gc_handle); }
inline Object getObject() const { return object; }
inline u32 getGCHandle() const { return gc_handle; }
}
inline ~ObjectHandle() {
if(gc_handle)
mono_gchandle_free(gc_handle);
}
inline Object getObject() const {
return mono_gchandle_get_target(gc_handle);
}
};
}

View File

@ -11,7 +11,7 @@
using namespace ougge;
#define GAMEOBJECTPOOL_SIZE 64*1024
#define GAMEOBJECTPOOL_SIZE 64
#define optime(N, LABEL, CODE) {\
nsec_t b = getMonotonicTimeNsec();\
@ -43,21 +43,20 @@ int main(int argc, const char** argv){
auto a = mono.loadAssembly("Ougge.dll");
MonoClass* gameObjectClass = a->getClass("Ougge", "GameObject");
MonoObject* exampleObjectManaged = mono_object_new(mono.getDomain(), gameObjectClass);
u64 obj_id = 0;
auto pair = p.emplace(GameObject(exampleObjectManaged));
auto pair = p.emplace(GameObject(mono_object_new(mono.getDomain(), gameObjectClass)));
Mono::ObjectHandle& exampleObjectHandle = pair.second.getObjectHandle();
auto gameObjectCtor = Mono::Method<void(u64, u32)>(gameObjectClass, ".ctor");
gameObjectCtor(exampleObjectManaged, obj_id++, pair.first);
gameObjectCtor(exampleObjectHandle.getObject(), obj_id++, pair.first);
auto exampleObjectUpdate = Mono::Method<void(f64)>(gameObjectClass, "InvokeUpdate");
updateCallbacks.push_back([exampleObjectManaged, exampleObjectUpdate](f64 deltaTime) -> void {
exampleObjectUpdate(exampleObjectManaged, deltaTime);
updateCallbacks.push_back([&exampleObjectHandle, exampleObjectUpdate](f64 deltaTime) -> void {
exampleObjectUpdate(exampleObjectHandle.getObject(), deltaTime);
});
auto tryCreateComponent = Mono::Method<Mono::Bool(Mono::String)>(gameObjectClass, "TryCreateComponent_internal");
Mono::String componentNameManaged = mono_string_new(mono.getDomain(), "Ougge.ExampleComponent");
// Mono::ObjectHandle componentNameObjectHandle((MonoObject*)(void*)componentNameManaged);
Mono::Bool created = tryCreateComponent(exampleObjectManaged, componentNameManaged);
Mono::Bool created = tryCreateComponent(exampleObjectHandle.getObject(), componentNameManaged);
if(!created.wide_bool)
throw UsefulException("couldn't create ExampleComponent");