/* * 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; } } } }