*/
using System;
-using System.Collections.Generic;
+using System.Collections.Concurrent;
using System.Threading;
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>();
}
/// <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;
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;
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;
}
}
}
+ 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!");
+ }
+ }
+
+
}
}