Merge branch 'master' into mac
This commit is contained in:
@@ -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, ¶m);
|
||||
}
|
||||
}
|
||||
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, ¶m);
|
||||
}
|
||||
}
|
||||
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);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user