/*
* Copyright(c) 2017 Samsung Electronics Co., Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
using System;
using System.Collections.Generic;
using System.Threading;
namespace Tizen.NUI
{
///
/// This is used to store a mapping between C++ base handle objects and it's C# instances.
///
///
internal sealed class Registry
{
private static readonly Registry registry = new Registry();
///
/// static initialization singleton
///
internal static Registry Instance
{
get { return registry; }
}
///
/// Given a C++ object, the dictionary allows us to find which C# object it belongs to.
/// By keeping the weak reference only, it will allow the object to be garbage collected.
///
private Dictionary _controlMap;
private Registry()
{
_controlMap = new Dictionary();
}
///
/// Stores the mapping between this instance of BaseHandle (C# base class) and native part.
///
/// The instance of BaseHandle (C# base class).
internal static void Register(BaseHandle baseHandle)
{
if(savedApplicationThread?.ManagedThreadId != Thread.CurrentThread.ManagedThreadId)
{
throw new global::System.ApplicationException("NUI object is attempt to be created in another thread. It should be created in main thread only!");
}
// We store a pointer to the RefObject for the control
RefObject refObj = baseHandle.GetObjectPtr();
IntPtr refCptr = (IntPtr)RefObject.getCPtr(refObj);
//NUILog.Debug("Storing ref object cptr in control map Hex: {0:X}" + refCptr);
if (!Instance._controlMap.ContainsKey(refCptr))
{
Instance._controlMap.Add(refCptr, new WeakReference(baseHandle, false));
}
return;
}
///
/// Removes this instance of BaseHandle (C# base class) and native part from the mapping table.
///
/// The instance of BaseHandle (C# base class)
internal static void Unregister(BaseHandle baseHandle)
{
RefObject refObj = baseHandle.GetObjectPtr();
IntPtr refCptr = (IntPtr)RefObject.getCPtr(refObj);
if (Instance._controlMap.ContainsKey(refCptr))
{
Instance._controlMap.Remove(refCptr);
}
return;
}
internal static BaseHandle GetManagedBaseHandleFromNativePtr(BaseHandle baseHandle)
{
RefObject refObj = baseHandle.GetObjectPtr();
IntPtr refObjectPtr = (IntPtr)RefObject.getCPtr(refObj);
// we store a dictionary of ref-obects (C++ land) to managed obects (C# land)
return GetManagedBaseHandleFromRefObject(refObjectPtr);
}
internal static BaseHandle GetManagedBaseHandleFromNativePtr(IntPtr cPtr)
{
IntPtr refObjectPtr = NDalicPINVOKE.GetRefObjectPtr(cPtr);
// we store a dictionary of ref-obects (C++ land) to managed obects (C# land)
return GetManagedBaseHandleFromRefObject(refObjectPtr);
}
internal static BaseHandle GetManagedBaseHandleFromRefObject(IntPtr refObjectPtr)
{
// we store a dictionary of ref-obects (C++ land) to managed obects (C# land)
WeakReference weakReference;
if (Instance._controlMap.TryGetValue(refObjectPtr, out weakReference))
{
if(weakReference == null) { throw new System.InvalidOperationException("Error! NUI Registry weakReference should not be NULL!"); }
BaseHandle ret = weakReference.Target as BaseHandle;
return ret;
}
else
{
return null;
}
}
private static Thread savedApplicationThread;
internal Thread SavedApplicationThread
{
get
{
return savedApplicationThread;
}
set
{
savedApplicationThread = value;
}
}
}
}