[NUI] Change all CallingConvention to `Cdecl`
[platform/core/csapi/tizenfx.git] / src / Tizen.NUI / src / public / Common / PropertyNotification.cs
index 656dca4..c323adb 100755 (executable)
@@ -29,8 +29,8 @@ namespace Tizen.NUI
     public class PropertyNotification : BaseHandle
     {
 
-        private DaliEventHandler<object, NotifyEventArgs> _propertyNotificationNotifyEventHandler;
-        private NotifyEventCallbackDelegate _propertyNotificationNotifyEventCallbackDelegate;
+        private DaliEventHandler<object, NotifyEventArgs> propertyNotificationNotifyEventHandler;
+        private NotifyEventCallbackDelegate propertyNotificationNotifyEventCallback;
 
         /// <summary>
         /// Create a instance of PropertyNotification.
@@ -54,7 +54,7 @@ namespace Tizen.NUI
         {
         }
 
-        [UnmanagedFunctionPointer(CallingConvention.StdCall)]
+        [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
         private delegate void NotifyEventCallbackDelegate(IntPtr propertyNotification);
 
         ///<summary>
@@ -66,24 +66,29 @@ namespace Tizen.NUI
         {
             add
             {
-                // Restricted to only one listener
-                if (_propertyNotificationNotifyEventHandler == null)
+                if (propertyNotificationNotifyEventHandler == null)
                 {
-                    _propertyNotificationNotifyEventHandler += value;
-
-                    _propertyNotificationNotifyEventCallbackDelegate = new NotifyEventCallbackDelegate(OnPropertyNotificationNotify);
-                    this.NotifySignal().Connect(_propertyNotificationNotifyEventCallbackDelegate);
+                    propertyNotificationNotifyEventCallback = OnPropertyNotificationNotify;
+                    using PropertyNotifySignal signal = new PropertyNotifySignal(Interop.PropertyNotification.NotifySignal(SwigCPtr), false);
+                    signal?.Connect(propertyNotificationNotifyEventCallback);
                 }
+                propertyNotificationNotifyEventHandler += value;
             }
-
             remove
             {
-                if (_propertyNotificationNotifyEventHandler != null)
+                propertyNotificationNotifyEventHandler -= value;
+                if (propertyNotificationNotifyEventHandler == null)
                 {
-                    this.NotifySignal().Disconnect(_propertyNotificationNotifyEventCallbackDelegate);
+                    using PropertyNotifySignal signal = new PropertyNotifySignal(Interop.PropertyNotification.NotifySignal(SwigCPtr), false);
+                    if (signal?.Empty() == false)
+                    {
+                        signal?.Disconnect(propertyNotificationNotifyEventCallback);
+                        if (signal?.Empty() == true)
+                        {
+                            propertyNotificationNotifyEventCallback = null;
+                        }
+                    }
                 }
-
-                _propertyNotificationNotifyEventHandler -= value;
             }
         }
 
@@ -117,7 +122,7 @@ namespace Tizen.NUI
 
         /// <summary>
         /// Get property notification from Intptr.<br/>
-        /// This should be internal, please do not use.
+        /// This should be internal, do not use.
         /// </summary>
         /// <param name="cPtr">An object of IntPtr type.</param>
         /// <returns>An object of the PropertyNotification type.</returns>
@@ -176,9 +181,10 @@ namespace Tizen.NUI
         /// <since_tizen> 4 </since_tizen>
         public Animatable GetTarget()
         {
-            BaseHandle ret = Registry.GetManagedBaseHandleFromNativePtr(Interop.PropertyNotification.GetTarget(SwigCPtr));
+            //to fix memory leak issue, match the handle count with native side.
+            Animatable ret = this.GetInstanceSafely<Animatable>(Interop.PropertyNotification.GetTarget(SwigCPtr));
             if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
-            return ret as Animatable;
+            return ret;
         }
 
         /// <summary>
@@ -229,19 +235,38 @@ namespace Tizen.NUI
         }
 
         /// <summary>
-        /// Connects to this signal to be notified when the notification has occurred.
+        /// override it to clean-up your own resources.
         /// </summary>
-        /// <returns>A signal object to Connect() with</returns>
-        internal PropertyNotifySignal NotifySignal()
+        /// <param name="type"></param>
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        protected override void Dispose(DisposeTypes type)
         {
-            PropertyNotifySignal ret = new PropertyNotifySignal(Interop.PropertyNotification.NotifySignal(SwigCPtr), false);
-            if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
-            return ret;
-        }
+            if (disposed)
+            {
+                return;
+            }
 
-        internal static global::System.Runtime.InteropServices.HandleRef getCPtr(PropertyNotification obj)
-        {
-            return (obj == null) ? new global::System.Runtime.InteropServices.HandleRef(null, global::System.IntPtr.Zero) : obj.SwigCPtr;
+            if (type == DisposeTypes.Explicit)
+            {
+                //Called by User
+                //Release your own managed resources here.
+                //You should release all of your own disposable objects here.
+            }
+
+            //Release your own unmanaged resources here.
+            //You should not access any managed member here except static instance.
+            //because the execution order of Finalizes is non-deterministic.
+
+            if (HasBody())
+            {
+                if (propertyNotificationNotifyEventCallback != null)
+                {
+                    using PropertyNotifySignal signal = new PropertyNotifySignal(Interop.PropertyNotification.NotifySignal(SwigCPtr), false);
+                    signal?.Disconnect(propertyNotificationNotifyEventCallback);
+                    propertyNotificationNotifyEventCallback = null;
+                }
+            }
+            base.Dispose(type);
         }
 
         /// This will not be public opened.
@@ -254,13 +279,50 @@ namespace Tizen.NUI
         // Callback for PropertyNotification NotifySignal
         private void OnPropertyNotificationNotify(IntPtr propertyNotification)
         {
-            NotifyEventArgs e = new NotifyEventArgs();
-            e.PropertyNotification = GetPropertyNotificationFromPtr(propertyNotification);
+            if (IsNativeHandleInvalid())
+            {
+                if (this.Disposed)
+                {
+                    if (propertyNotificationNotifyEventHandler != null)
+                    {
+                        var process = global::System.Diagnostics.Process.GetCurrentProcess();
+                        var processId = process?.Id ?? -1;
+                        var thread = global::System.Threading.Thread.CurrentThread.ManagedThreadId;
+                        var me = this.GetType().FullName;
 
-            if (_propertyNotificationNotifyEventHandler != null)
+                        Tizen.Log.Error("NUI", $"Error! NUI's native dali object is already disposed. " +
+                            $"OR the native dali object handle of NUI becomes null! \n" +
+                            $" process:{processId} thread:{thread}, isDisposed:{this.Disposed}, isDisposeQueued:{this.IsDisposeQueued}, me:{me}\n");
+
+                        process?.Dispose();
+                    }
+                }
+                else
+                {
+                    if (this.IsDisposeQueued)
+                    {
+                        var process = global::System.Diagnostics.Process.GetCurrentProcess();
+                        var processId = process?.Id ?? -1;
+                        var thread = global::System.Threading.Thread.CurrentThread.ManagedThreadId;
+                        var me = this.GetType().FullName;
+
+                        //in this case, this object is ready to be disposed waiting on DisposeQueue, so event callback should not be invoked!
+                        Tizen.Log.Error("NUI", "in this case, the View object is ready to be disposed waiting on DisposeQueue, so event callback should not be invoked! just return here! \n" +
+                            $"process:{processId} thread:{thread}, isDisposed:{this.Disposed}, isDisposeQueued:{this.IsDisposeQueued}, me:{me}\n");
+
+                        process?.Dispose();
+                        return;
+                    }
+                }
+            }
+
+            if (propertyNotificationNotifyEventHandler != null)
             {
+                NotifyEventArgs e = new NotifyEventArgs();
+                e.PropertyNotification = GetPropertyNotificationFromPtr(propertyNotification);
+
                 //here we send all data to user event handlers
-                _propertyNotificationNotifyEventHandler(this, e);
+                propertyNotificationNotifyEventHandler(this, e);
             }
         }
 
@@ -270,7 +332,7 @@ namespace Tizen.NUI
         /// <since_tizen> 3 </since_tizen>
         public class NotifyEventArgs : EventArgs
         {
-            private PropertyNotification _propertyNotification;
+            private PropertyNotification propertyNotification;
 
             ///<summary>
             /// PropertyNotification - is the PropertyNotification handle that has the notification properties.
@@ -280,11 +342,11 @@ namespace Tizen.NUI
             {
                 get
                 {
-                    return _propertyNotification;
+                    return propertyNotification;
                 }
                 set
                 {
-                    _propertyNotification = value;
+                    propertyNotification = value;
                 }
             }
         }