[4.0] depense code for TriggerEvent::Triggered callback null-reference issue
[platform/core/csapi/tizenfx.git] / src / Tizen.NUI / src / internal / Registry.cs
1 /*
2  * Copyright(c) 2017 Samsung Electronics Co., Ltd.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  */
17
18 using System;
19 using System.Collections.Generic;
20 using System.Threading;
21
22 namespace Tizen.NUI
23 {
24     /// <summary>
25     /// This is used to store a mapping between C++ base handle objects and it's C# instances.
26     ///
27     /// </summary>
28     internal sealed class Registry
29     {
30         private static readonly Registry registry = new Registry();
31
32         /// <summary>
33         /// static initialization singleton
34         /// </summary>
35         internal static Registry Instance
36         {
37             get { return registry; }
38         }
39
40         /// <summary>
41         /// Given a C++ object, the dictionary allows us to find which C# object it belongs to.
42         /// By keeping the weak reference only, it will allow the object to be garbage collected.
43         /// </summary>
44         private Dictionary<IntPtr, WeakReference> _controlMap;
45
46         private Registry()
47         {
48             _controlMap = new Dictionary<IntPtr, WeakReference>();
49         }
50
51
52         /// <summary>
53         /// Stores the mapping between this instance of BaseHandle (C# base class) and native part.
54         /// </summary>
55         /// <param name="baseHandle">The instance of BaseHandle (C# base class).</param>
56         internal static void Register(BaseHandle baseHandle)
57         {
58             if(savedApplicationThread?.ManagedThreadId != Thread.CurrentThread.ManagedThreadId)
59             {
60                 throw new global::System.ApplicationException("NUI object is attempt to be created in another thread. It should be created in main thread only!");
61             }
62
63             // We store a pointer to the RefObject for the control
64             RefObject refObj = baseHandle.GetObjectPtr();
65             IntPtr refCptr = (IntPtr)RefObject.getCPtr(refObj);
66
67             //NUILog.Debug("Storing ref object cptr in control map Hex: {0:X}" + refCptr);
68
69             if (!Instance._controlMap.ContainsKey(refCptr))
70             {
71                 Instance._controlMap.Add(refCptr, new WeakReference(baseHandle, false));
72             }
73
74             return;
75         }
76
77         /// <summary>
78         /// Removes this instance of BaseHandle (C# base class) and native part from the mapping table.
79         /// </summary>
80         /// <param name="baseHandle"> The instance of BaseHandle (C# base class)</param>
81         internal static void Unregister(BaseHandle baseHandle)
82         {
83             RefObject refObj = baseHandle.GetObjectPtr();
84             IntPtr refCptr = (IntPtr)RefObject.getCPtr(refObj);
85
86             if (Instance._controlMap.ContainsKey(refCptr))
87             {
88                 Instance._controlMap.Remove(refCptr);
89             }
90
91             return;
92         }
93
94         internal static BaseHandle GetManagedBaseHandleFromNativePtr(BaseHandle baseHandle)
95         {
96             RefObject refObj = baseHandle.GetObjectPtr();
97             IntPtr refObjectPtr = (IntPtr)RefObject.getCPtr(refObj);
98
99             // we store a dictionary of ref-obects (C++ land) to managed obects (C# land)
100             return GetManagedBaseHandleFromRefObject(refObjectPtr);
101         }
102
103         internal static BaseHandle GetManagedBaseHandleFromNativePtr(IntPtr cPtr)
104         {
105             IntPtr refObjectPtr = NDalicPINVOKE.GetRefObjectPtr(cPtr);
106
107             // we store a dictionary of ref-obects (C++ land) to managed obects (C# land)
108             return GetManagedBaseHandleFromRefObject(refObjectPtr);
109         }
110
111         internal static BaseHandle GetManagedBaseHandleFromRefObject(IntPtr refObjectPtr)
112         {
113             // we store a dictionary of ref-obects (C++ land) to managed obects (C# land)
114             WeakReference weakReference;
115
116             if (Instance._controlMap.TryGetValue(refObjectPtr, out weakReference))
117             {
118                 if(weakReference == null) { throw new System.InvalidOperationException("Error! NUI Registry weakReference should not be NULL!"); }
119                 BaseHandle ret = weakReference.Target as BaseHandle;
120                 return ret;
121             }
122             else
123             {
124                 return null;
125             }
126         }
127
128         private static Thread savedApplicationThread;
129         internal Thread SavedApplicationThread
130         {
131             get
132             {
133                 return savedApplicationThread;
134             }
135             set
136             {
137                 savedApplicationThread = value;
138             }
139         }
140
141     }
142 }