[NUI] Change Registry as concurrent collection for protection code (#113)
authordongsug-song <35130733+dongsug-song@users.noreply.github.com>
Wed, 7 Feb 2018 08:42:56 +0000 (17:42 +0900)
committerGitHub <noreply@github.com>
Wed, 7 Feb 2018 08:42:56 +0000 (17:42 +0900)
src/Tizen.NUI/src/internal/Registry.cs

index 2c0ee0a..6143900 100755 (executable)
@@ -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.
         /// </summary>
-        private Dictionary<IntPtr, WeakReference> _controlMap;
+        private ConcurrentDictionary<IntPtr, WeakReference> _controlMap;
 
         private Registry()
         {
-            _controlMap = new Dictionary<IntPtr, WeakReference>();
+            _controlMap = new ConcurrentDictionary<IntPtr, WeakReference>();
         }
 
 
@@ -55,16 +55,24 @@ namespace Tizen.NUI
         /// <param name="baseHandle">The instance of BaseHandle (C# base class).</param>
         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!");
+            }
+        }
+
+
     }
 }