From 6fa11cf3a603739e37aa605fa9de79e97374c61b Mon Sep 17 00:00:00 2001 From: dongsug-song <35130733+dongsug-song@users.noreply.github.com> Date: Wed, 7 Feb 2018 17:42:56 +0900 Subject: [PATCH] [NUI] Change Registry as concurrent collection for protection code (#113) --- src/Tizen.NUI/src/internal/Registry.cs | 64 ++++++++++++++++++++++++++++------ 1 file changed, 53 insertions(+), 11 deletions(-) diff --git a/src/Tizen.NUI/src/internal/Registry.cs b/src/Tizen.NUI/src/internal/Registry.cs index 2c0ee0a..6143900 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 + { + NUILog.Debug($"Unregister: type={baseHandle?.GetTypeName()} refCptr=0x{refCptr.ToInt64():X}"); + } + + RegistryCurrentThreadCheck(); + + WeakReference removeTarget; + if(Instance._controlMap.TryRemove(refCptr, out removeTarget) != true) { - Instance._controlMap.Remove(refCptr); + NUILog.Debug("something wrong when removing refCptr!"); } return; @@ -108,16 +128,26 @@ namespace Tizen.NUI { 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}"); + } + + 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; } @@ -140,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