Merge branch 'master' into mac

This commit is contained in:
Wojtek Figat
2022-01-09 19:15:15 +01:00
94 changed files with 1726 additions and 499 deletions

View File

@@ -38,20 +38,32 @@ ScriptingObject::ScriptingObject(const SpawnParams& params)
ScriptingObject::~ScriptingObject()
{
// Ensure that GC handle is empty
ASSERT(_gcHandle == 0);
// Ensure that object has been already unregistered
if (IsRegistered())
UnregisterObject();
Deleted(this);
// Get rid of managed object
ScriptingObject::DestroyManaged();
ASSERT(_gcHandle == 0);
// Handle custom scripting objects removing
if (Flags & ObjectFlags::IsCustomScriptingType)
{
_type.Module->OnObjectDeleted(this);
}
// Ensure that object has been already unregistered
if (IsRegistered())
UnregisterObject();
}
ScriptingObject* ScriptingObject::NewObject(const ScriptingTypeHandle& typeHandle)
{
if (!typeHandle)
return nullptr;
auto& type = typeHandle.GetType();
if (type.Type != ScriptingTypes::Script)
return nullptr;
const ScriptingObjectSpawnParams params(Guid::New(), typeHandle);
return type.Script.Spawn(params);
}
MObject* ScriptingObject::GetManagedInstance() const
@@ -207,18 +219,49 @@ void ScriptingObject::OnManagedInstanceDeleted()
// Unregister object
if (IsRegistered())
UnregisterObject();
// Self destruct
DeleteObject();
}
void ScriptingObject::OnScriptingDispose()
{
// Delete C# object
if (IsRegistered())
UnregisterObject();
DestroyManaged();
}
// Delete C++ object
DeleteObject();
bool ScriptingObject::CreateManaged()
{
#if USE_MONO
MonoObject* managedInstance = CreateManagedInternal();
if (!managedInstance)
return true;
// Prevent form object GC destruction
auto handle = mono_gchandle_new(managedInstance, false);
auto oldHandle = Platform::InterlockedCompareExchange((int32*)&_gcHandle, *(int32*)&handle, 0);
if (*(uint32*)&oldHandle != 0)
{
// Other thread already created the object before
if (const auto monoClass = GetClass())
{
// Reset managed to unmanaged pointer
const MField* monoUnmanagedPtrField = monoClass->GetField(ScriptingObject_unmanagedPtr);
if (monoUnmanagedPtrField)
{
void* param = nullptr;
monoUnmanagedPtrField->SetValue(managedInstance, &param);
}
}
mono_gchandle_free(handle);
return true;
}
#endif
// Ensure to be registered
if (!IsRegistered())
RegisterObject();
return false;
}
#if USE_MONO
@@ -233,8 +276,16 @@ MonoObject* ScriptingObject::CreateManagedInternal()
return nullptr;
}
// Ensure to have managed domain attached (this can be called from custom native thread, eg. content loader)
auto domain = mono_domain_get();
if (!domain)
{
MCore::AttachThread();
domain = mono_domain_get();
}
// Allocate managed instance
MonoObject* managedInstance = mono_object_new(mono_domain_get(), monoClass->GetNative());
MonoObject* managedInstance = mono_object_new(domain, monoClass->GetNative());
if (managedInstance == nullptr)
{
LOG(Warning, "Failed to create new instance of the object of type {0}", String(monoClass->GetFullName()));
@@ -358,7 +409,7 @@ void ScriptingObject::OnDeleteObject()
UnregisterObject();
// Base
RemovableObject::OnDeleteObject();
Object::OnDeleteObject();
}
String ScriptingObject::ToString() const
@@ -371,6 +422,24 @@ ManagedScriptingObject::ManagedScriptingObject(const SpawnParams& params)
{
}
void ManagedScriptingObject::OnManagedInstanceDeleted()
{
// Base
ScriptingObject::OnManagedInstanceDeleted();
// Self destruct
DeleteObject();
}
void ManagedScriptingObject::OnScriptingDispose()
{
// Base
ScriptingObject::OnScriptingDispose();
// Self destruct
DeleteObject();
}
bool ManagedScriptingObject::CreateManaged()
{
#if USE_MONO
@@ -411,70 +480,6 @@ PersistentScriptingObject::PersistentScriptingObject(const SpawnParams& params)
{
}
PersistentScriptingObject::~PersistentScriptingObject()
{
PersistentScriptingObject::DestroyManaged();
}
void PersistentScriptingObject::OnManagedInstanceDeleted()
{
// Cleanup
if (_gcHandle)
{
#if USE_MONO
mono_gchandle_free(_gcHandle);
#endif
_gcHandle = 0;
}
// But do not delete itself
}
void PersistentScriptingObject::OnScriptingDispose()
{
// Delete C# object
if (IsRegistered())
UnregisterObject();
DestroyManaged();
// Don't delete C++ object
}
bool PersistentScriptingObject::CreateManaged()
{
#if USE_MONO
MonoObject* managedInstance = CreateManagedInternal();
if (!managedInstance)
return true;
// Prevent form object GC destruction
auto handle = mono_gchandle_new(managedInstance, false);
auto oldHandle = Platform::InterlockedCompareExchange((int32*)&_gcHandle, *(int32*)&handle, 0);
if (*(uint32*)&oldHandle != 0)
{
// Other thread already created the object before
if (const auto monoClass = GetClass())
{
// Reset managed to unmanaged pointer
const MField* monoUnmanagedPtrField = monoClass->GetField(ScriptingObject_unmanagedPtr);
if (monoUnmanagedPtrField)
{
void* param = nullptr;
monoUnmanagedPtrField->SetValue(managedInstance, &param);
}
}
mono_gchandle_free(handle);
return true;
}
#endif
// Ensure to be registered
if (!IsRegistered())
RegisterObject();
return false;
}
class ScriptingObjectInternal
{
public:
@@ -746,7 +751,7 @@ public:
static ScriptingObject* Spawn(const ScriptingObjectSpawnParams& params)
{
return New<PersistentScriptingObject>(params);
return New<ScriptingObject>(params);
}
};