From 6193f242e0f551ac92d5bd1c0a91946dca62bcfa Mon Sep 17 00:00:00 2001 From: dongsug-song <35130733+dongsug-song@users.noreply.github.com> Date: Thu, 10 May 2018 16:48:05 +0900 Subject: [PATCH] [NUI] Change Registry as concurrent collection for protection code (#114) --- src/Tizen.NUI/src/internal/Registry.cs | 80 ++++++++++++++++++++++++---------- 1 file changed, 56 insertions(+), 24 deletions(-) diff --git a/src/Tizen.NUI/src/internal/Registry.cs b/src/Tizen.NUI/src/internal/Registry.cs index fc254b8..a05a58f 100755 --- a/src/Tizen.NUI/src/internal/Registry.cs +++ b/src/Tizen.NUI/src/internal/Registry.cs @@ -16,7 +16,7 @@ */ using System; -using System.Collections.Generic; +using System.Collections.Concurrent; using System.Threading; namespace Tizen.NUI @@ -41,11 +41,11 @@ namespace Tizen.NUI /// 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 ConcurrentDictionary _controlMap; private Registry() { - _controlMap = new Dictionary(); + _controlMap = new ConcurrentDictionary(); } @@ -55,16 +55,24 @@ namespace Tizen.NUI /// The instance of BaseHandle (C# base class). internal static void Register(BaseHandle baseHandle) { - // 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(baseHandle == null) + { + NUILog.Debug($"Register: baseHandle == null ! means native object is null!"); + } + else + { + NUILog.Debug($"Register: type={baseHandle?.GetTypeName()} refCptr=0x{refCptr.ToInt64():X}"); + } + + RegistryCurrentThreadCheck(); - if (!Instance._controlMap.ContainsKey(refCptr)) + if(Instance._controlMap.TryAdd(refCptr, new WeakReference(baseHandle, false)) != true) { - Instance._controlMap.Add(refCptr, new WeakReference(baseHandle, false)); + NUILog.Debug("refCptr is already exist! OR something wrong!"); } return; @@ -79,9 +87,21 @@ namespace Tizen.NUI RefObject refObj = baseHandle.GetObjectPtr(); IntPtr refCptr = (IntPtr)RefObject.getCPtr(refObj); - if (Instance._controlMap.ContainsKey(refCptr)) + if (baseHandle == null) + { + NUILog.Debug($"Unregister: baseHandle == null ! means native object is null!"); + } + else { - Instance._controlMap.Remove(refCptr); + NUILog.Debug($"Unregister: type={baseHandle?.GetTypeName()} refCptr=0x{refCptr.ToInt64():X}"); + } + + RegistryCurrentThreadCheck(); + + WeakReference removeTarget; + if(Instance._controlMap.TryRemove(refCptr, out removeTarget) != true) + { + NUILog.Debug("something wrong when removing refCptr!"); } return; @@ -92,42 +112,42 @@ namespace Tizen.NUI RefObject refObj = baseHandle.GetObjectPtr(); IntPtr refObjectPtr = (IntPtr)RefObject.getCPtr(refObj); - if (refObjectPtr != null) - { // we store a dictionary of ref-obects (C++ land) to managed obects (C# land) return GetManagedBaseHandleFromRefObject(refObjectPtr); } - else - { - NUILog.Error("NUI Registry RefObjectPtr is NULL!"); - return null; - } - } internal static BaseHandle GetManagedBaseHandleFromNativePtr(IntPtr cPtr) { IntPtr refObjectPtr = NDalicPINVOKE.GetRefObjectPtr(cPtr); - if (refObjectPtr != null) - { // we store a dictionary of ref-obects (C++ land) to managed obects (C# land) return GetManagedBaseHandleFromRefObject(refObjectPtr); } - else + + internal static BaseHandle GetManagedBaseHandleFromRefObject(IntPtr refObjectPtr) + { + if (refObjectPtr == global::System.IntPtr.Zero) { - NUILog.Error("NUI Registry RefObjectPtr is NULL!"); + NUILog.Debug("Registry refObjectPtr is NULL! This means bind native object is NULL!"); return null; } + else + { + NUILog.Debug($"refObjectPtr=0x{refObjectPtr.ToInt64():X}"); } - internal static BaseHandle GetManagedBaseHandleFromRefObject(IntPtr refObjectPtr) - { + RegistryCurrentThreadCheck(); + // 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!"); } + if(weakReference == null) + { + throw new System.InvalidOperationException("Error! NUI Registry weakReference should not be NULL!"); + } + BaseHandle ret = weakReference.Target as BaseHandle; return ret; } @@ -150,5 +170,17 @@ namespace Tizen.NUI } } + private static void RegistryCurrentThreadCheck() + { + int currentId = Thread.CurrentThread.ManagedThreadId; + int mainThreadId = savedApplicationThread.ManagedThreadId; + + if(currentId != mainThreadId) + { + Tizen.Log.Fatal("NUI", $"Error! current thread({currentId}) which is NOT main thread({mainThreadId}) utilizes NUI object!"); + } + } + + } } -- 2.7.4