2 * Copyright(c) 2018 Samsung Electronics Co., Ltd.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
19 using System.Collections.Concurrent;
20 using System.Threading;
25 /// This is used to store a mapping between C++ base handle objects and it's C# instances.
28 internal sealed class Registry
30 private static readonly Registry registry = new Registry();
33 /// static initialization singleton
35 internal static Registry Instance
37 get { return registry; }
41 /// Given a C++ object, the dictionary allows us to find which C# object it belongs to.
42 /// By keeping the weak reference only, it will allow the object to be garbage collected.
44 private ConcurrentDictionary<IntPtr, WeakReference> _controlMap;
48 _controlMap = new ConcurrentDictionary<IntPtr, WeakReference>();
53 /// Stores the mapping between this instance of BaseHandle (C# base class) and native part.
55 /// <param name="baseHandle">The instance of BaseHandle (C# base class).</param>
56 internal static void Register(BaseHandle baseHandle)
58 // We store a pointer to the RefObject for the control
59 RefObject refObj = baseHandle.GetObjectPtr();
60 IntPtr refCptr = (IntPtr)RefObject.getCPtr(refObj);
62 if(baseHandle == null)
64 NUILog.Debug($"Register: baseHandle == null ! means native object is null!");
68 NUILog.Debug($"Register: type={baseHandle?.GetTypeName()} refCptr=0x{refCptr.ToInt64():X}");
71 RegistryCurrentThreadCheck();
73 if(Instance._controlMap.TryAdd(refCptr, new WeakReference(baseHandle, false)) != true)
75 NUILog.Debug("refCptr is already exist! OR something wrong!");
82 /// Removes this instance of BaseHandle (C# base class) and native part from the mapping table.
84 /// <param name="baseHandle"> The instance of BaseHandle (C# base class)</param>
85 internal static void Unregister(BaseHandle baseHandle)
87 RefObject refObj = baseHandle.GetObjectPtr();
88 IntPtr refCptr = (IntPtr)RefObject.getCPtr(refObj);
90 if (baseHandle == null)
92 NUILog.Debug($"Unregister: baseHandle == null ! means native object is null!");
96 NUILog.Debug($"Unregister: type={baseHandle?.GetTypeName()} refCptr=0x{refCptr.ToInt64():X}");
99 RegistryCurrentThreadCheck();
101 WeakReference removeTarget;
102 if(Instance._controlMap.TryRemove(refCptr, out removeTarget) != true)
104 NUILog.Debug("something wrong when removing refCptr!");
110 internal static BaseHandle GetManagedBaseHandleFromNativePtr(BaseHandle baseHandle)
112 RefObject refObj = baseHandle.GetObjectPtr();
113 IntPtr refObjectPtr = (IntPtr)RefObject.getCPtr(refObj);
115 // we store a dictionary of ref-obects (C++ land) to managed obects (C# land)
116 return GetManagedBaseHandleFromRefObject(refObjectPtr);
119 internal static BaseHandle GetManagedBaseHandleFromNativePtr(IntPtr cPtr)
121 IntPtr refObjectPtr = NDalicPINVOKE.GetRefObjectPtr(cPtr);
123 // we store a dictionary of ref-obects (C++ land) to managed obects (C# land)
124 return GetManagedBaseHandleFromRefObject(refObjectPtr);
127 internal static BaseHandle GetManagedBaseHandleFromRefObject(IntPtr refObjectPtr)
129 if (refObjectPtr == global::System.IntPtr.Zero)
131 NUILog.Debug("Registry refObjectPtr is NULL! This means bind native object is NULL!");
136 NUILog.Debug($"refObjectPtr=0x{refObjectPtr.ToInt64():X}");
139 RegistryCurrentThreadCheck();
141 // we store a dictionary of ref-obects (C++ land) to managed obects (C# land)
142 WeakReference weakReference;
144 if (Instance._controlMap.TryGetValue(refObjectPtr, out weakReference))
146 if(weakReference == null)
148 throw new System.InvalidOperationException("Error! NUI Registry weakReference should not be NULL!");
151 BaseHandle ret = weakReference.Target as BaseHandle;
160 private static Thread savedApplicationThread;
161 internal Thread SavedApplicationThread
165 return savedApplicationThread;
169 savedApplicationThread = value;
173 private static void RegistryCurrentThreadCheck()
175 int currentId = Thread.CurrentThread.ManagedThreadId;
176 int mainThreadId = savedApplicationThread.ManagedThreadId;
178 if(currentId != mainThreadId)
180 Tizen.Log.Fatal("NUI", $"Error! current thread({currentId}) which is NOT main thread({mainThreadId}) utilizes NUI object!");