+/*
+ * Copyright(c) 2018 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
-using System.Reflection;
using System;
-using System.Runtime.InteropServices;
-using System.Collections.Generic;
-using Tizen.NUI.BaseComponents;
+using System.Collections.Concurrent;
+using System.Threading;
namespace Tizen.NUI
{
/// </summary>
internal sealed class Registry
{
+ private static readonly Registry registry = new Registry();
+
/// <summary>
- /// The registry is a singleton.
+ /// static initialization singleton
/// </summary>
- private static Registry instance = null;
+ internal static Registry Instance
+ {
+ get { return registry; }
+ }
/// <summary>
/// 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>();
}
RefObject refObj = baseHandle.GetObjectPtr();
IntPtr refCptr = (IntPtr)RefObject.getCPtr(refObj);
- NUILog.Debug("________Storing ref object cptr in control map Hex: {0:X}" + refCptr);
+ 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))
+ RegistryCurrentThreadCheck();
+
+ WeakReference removeTarget;
+ if(Instance._controlMap.TryRemove(refCptr, out removeTarget) != true)
{
- Instance._controlMap.Remove(refCptr);
+ NUILog.Debug("something wrong when removing refCptr!");
}
return;
}
- private static Registry Instance
- {
- get
- {
- if (instance == null)
- {
- instance = new Registry();
- }
- return instance;
- }
- }
-
internal static BaseHandle GetManagedBaseHandleFromNativePtr(BaseHandle baseHandle)
{
RefObject refObj = baseHandle.GetObjectPtr();
internal static BaseHandle GetManagedBaseHandleFromRefObject(IntPtr refObjectPtr)
{
+ if (refObjectPtr == global::System.IntPtr.Zero)
+ {
+ 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!");
+ }
+
BaseHandle ret = weakReference.Target as BaseHandle;
return ret;
}
}
}
+ private static Thread savedApplicationThread;
+ internal Thread SavedApplicationThread
+ {
+ get
+ {
+ return savedApplicationThread;
+ }
+ set
+ {
+ savedApplicationThread = value;
+ }
+ }
+
+ private static void RegistryCurrentThreadCheck()
+ {
+ if(savedApplicationThread == null)
+ {
+ Tizen.Log.Fatal("NUI", $"Error! maybe main thread is created by other process ");
+ return;
+ }
+ 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!");
+ }
+ }
+
+
}
}