[NUI] Move WeakEvent to public and remove unused WeakEventHandler class
authorJiyun Yang <ji.yang@samsung.com>
Mon, 18 Mar 2024 11:13:14 +0000 (20:13 +0900)
committerJiyun Yang <ji.yang@samsung.com>
Thu, 21 Mar 2024 05:52:55 +0000 (14:52 +0900)
Signed-off-by: Jiyun Yang <ji.yang@samsung.com>
src/Tizen.NUI/src/internal/Common/WeakEvent.cs [deleted file]
src/Tizen.NUI/src/internal/Common/WeakEventHandler.cs [deleted file]
src/Tizen.NUI/src/public/Common/WeakEvent.cs [new file with mode: 0755]

diff --git a/src/Tizen.NUI/src/internal/Common/WeakEvent.cs b/src/Tizen.NUI/src/internal/Common/WeakEvent.cs
deleted file mode 100755 (executable)
index 1b12cef..0000000
+++ /dev/null
@@ -1,155 +0,0 @@
-/*
- * Copyright (c) 2020 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;
-using System.Collections.Generic;
-using System.Reflection;
-
-namespace Tizen.NUI
-{
-    internal class WeakEvent<T> where T : Delegate
-    {
-        private const int addThreshold = 1000; // Experimetal constant
-        private const int listLengthThreshold = 1000; // Experimetal constant
-        private int cleanUpAddCount = 0;
-        private List<WeakHandler<T>> handlers = new List<WeakHandler<T>>();
-
-        protected int Count => handlers.Count;
-
-        public virtual void Add(T handler)
-        {
-            handlers.Add(new WeakHandler<T>(handler));
-            OnCountIncreased();
-
-            CleanUpDeadHandlersIfNeeds();
-        }
-
-        public virtual void Remove(T handler)
-        {
-            int lastIndex = handlers.FindLastIndex(item => item.Equals(handler));
-
-            if (lastIndex >= 0)
-            {
-                handlers.RemoveAt(lastIndex);
-                OnCountDicreased();
-            }
-        }
-
-        public void Invoke(object sender, EventArgs args)
-        {
-            // Iterate copied one to prevent addition/removal item in the handler call.
-            var copiedArray = handlers.ToArray();
-            foreach (var item in copiedArray)
-            {
-                item.Invoke(sender, args);
-            }
-
-            // Clean up GC items
-            CleanUpDeadHandlers();
-        }
-
-        protected virtual void OnCountIncreased()
-        {
-        }
-
-
-        protected virtual void OnCountDicreased()
-        {
-        }
-
-        private void CleanUpDeadHandlersIfNeeds()
-        {
-            // Once the list count exceed 'listLengthThreshold', do the clean-up every 'addThreshold' add operations.
-            // When list count go below `listLengthThreshold` before clean-up, pause operation counting.
-            if (handlers.Count > listLengthThreshold && ++cleanUpAddCount > addThreshold)
-            {
-                CleanUpDeadHandlers();
-            }
-        }
-
-        private void CleanUpDeadHandlers()
-        {
-            cleanUpAddCount = 0;
-            int count = handlers.Count;
-            handlers.RemoveAll(item => !item.IsAlive);
-            if (count > handlers.Count) OnCountDicreased();
-        }
-
-        internal class WeakHandler<U> where U : Delegate
-        {
-            private WeakReference weakTarget; // Null value means the method is static.
-            private MethodInfo methodInfo;
-
-            public WeakHandler(U handler)
-            {
-                Delegate d = (Delegate)(object)handler;
-                if (d.Target != null) weakTarget = new WeakReference(d.Target);
-                methodInfo = d.Method;
-            }
-
-            private bool IsStatic => weakTarget == null;
-
-            public bool IsAlive
-            {
-                get
-                {
-                    var rooting = weakTarget?.Target;
-
-                    return IsStatic || !IsDisposed(rooting);
-                }
-            }
-
-            private static bool IsDisposed(object target)
-            {
-                if (target == null) return true;
-
-                if (target is BaseHandle basehandle) return basehandle.Disposed || basehandle.IsDisposeQueued;
-
-                if (target is Disposable disposable) return disposable.Disposed || disposable.IsDisposeQueued;
-
-                return false;
-            }
-
-            public bool Equals(U handler)
-            {
-                Delegate other = (Delegate)(object)handler;
-                bool isOtherStatic = other.Target == null;
-                return (isOtherStatic || weakTarget?.Target == other.Target) && methodInfo.Equals(other.Method);
-            }
-
-            public void Invoke(params object[] args)
-            {
-                if (IsStatic)
-                {
-                    Delegate.CreateDelegate(typeof(U), methodInfo).DynamicInvoke(args);
-                }
-                else
-                {
-                    // Because GC is done in other thread,
-                    // it needs to check again that the reference is still alive before calling method.
-                    // To do that, the reference should be assigned to the local variable first.
-                    var rooting = weakTarget.Target;
-
-                    if (IsAlive)
-                    {
-                        Delegate.CreateDelegate(typeof(U), rooting, methodInfo).DynamicInvoke(args);
-                    }
-                }
-            }
-        }
-    }
-}
diff --git a/src/Tizen.NUI/src/internal/Common/WeakEventHandler.cs b/src/Tizen.NUI/src/internal/Common/WeakEventHandler.cs
deleted file mode 100755 (executable)
index 016b8fd..0000000
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Copyright (c) 2021 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;
-using System.Reflection;
-
-namespace Tizen.NUI
-{
-    internal sealed class WeakEventHandler<TEventArgs> where TEventArgs : EventArgs
-    {
-        private readonly WeakReference targetReference;
-        private readonly MethodInfo method;
-
-        public WeakEventHandler(EventHandler<TEventArgs> callback)
-        {
-            method = callback.GetMethodInfo();
-            targetReference = new WeakReference(callback.Target, true);
-        }
-
-        public void Handler(object sender, TEventArgs e)
-        {
-            var target = targetReference.Target;
-            if (target != null)
-            {
-                var callback = (Action<object, TEventArgs>)method.CreateDelegate(typeof(Action<object, TEventArgs>), target);
-                if (callback != null)
-                {
-                    callback(sender, e);
-                }
-            }
-        }
-    }
-}
-
diff --git a/src/Tizen.NUI/src/public/Common/WeakEvent.cs b/src/Tizen.NUI/src/public/Common/WeakEvent.cs
new file mode 100755 (executable)
index 0000000..dc84a0c
--- /dev/null
@@ -0,0 +1,182 @@
+/*
+ * Copyright (c) 2020 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;
+using System.ComponentModel;
+using System.Collections.Generic;
+using System.Reflection;
+
+namespace Tizen.NUI
+{
+    /// <summary>
+    /// The WeakEvent without holding strong reference of event handler.
+    /// </summary>
+    [EditorBrowsable(EditorBrowsableState.Never)]
+    public class WeakEvent<T> where T : Delegate
+    {
+        private const int addThreshold = 1000; // Experimetal constant
+        private const int listLengthThreshold = 1000; // Experimetal constant
+        private int cleanUpAddCount = 0;
+        private List<WeakHandler<T>> handlers = new List<WeakHandler<T>>();
+
+        /// <summary>
+        /// The count of currently added event handlers.
+        /// </summary>
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        protected int Count => handlers.Count;
+
+        /// <summary>
+        /// Add an event handler.
+        /// </summary>
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        public virtual void Add(T handler)
+        {
+            handlers.Add(new WeakHandler<T>(handler));
+            OnCountIncreased();
+
+            CleanUpDeadHandlersIfNeeds();
+        }
+
+        /// <summary>
+        /// Remove last added event handler.
+        /// </summary>
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        public virtual void Remove(T handler)
+        {
+            int lastIndex = handlers.FindLastIndex(item => item.Equals(handler));
+
+            if (lastIndex >= 0)
+            {
+                handlers.RemoveAt(lastIndex);
+                OnCountDicreased();
+            }
+        }
+
+        /// <summary>
+        /// Invoke event handlers.
+        /// </summary>
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        public void Invoke(object sender, EventArgs args)
+        {
+            // Iterate copied one to prevent addition/removal item in the handler call.
+            var copiedArray = handlers.ToArray();
+            foreach (var item in copiedArray)
+            {
+                item.Invoke(sender, args);
+            }
+
+            // Clean up GC items
+            CleanUpDeadHandlers();
+        }
+
+        /// <summary>
+        /// Invoked when the event handler count is increased.
+        /// </summary>
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        protected virtual void OnCountIncreased()
+        {
+        }
+
+        /// <summary>
+        /// Invoked when the event handler count is decreased.
+        /// </summary>
+        protected virtual void OnCountDicreased()
+        {
+        }
+
+        private void CleanUpDeadHandlersIfNeeds()
+        {
+            // Once the list count exceed 'listLengthThreshold', do the clean-up every 'addThreshold' add operations.
+            // When list count go below `listLengthThreshold` before clean-up, pause operation counting.
+            if (handlers.Count > listLengthThreshold && ++cleanUpAddCount > addThreshold)
+            {
+                CleanUpDeadHandlers();
+            }
+        }
+
+        private void CleanUpDeadHandlers()
+        {
+            cleanUpAddCount = 0;
+            int count = handlers.Count;
+            handlers.RemoveAll(item => !item.IsAlive);
+            if (count > handlers.Count) OnCountDicreased();
+        }
+
+        internal class WeakHandler<U> where U : Delegate
+        {
+            private WeakReference weakTarget; // Null value means the method is static.
+            private MethodInfo methodInfo;
+
+            public WeakHandler(U handler)
+            {
+                Delegate d = (Delegate)(object)handler;
+                if (d.Target != null) weakTarget = new WeakReference(d.Target);
+                methodInfo = d.Method;
+            }
+
+            private bool IsStatic => weakTarget == null;
+
+            public bool IsAlive
+            {
+                get
+                {
+                    var rooting = weakTarget?.Target;
+
+                    return IsStatic || !IsDisposed(rooting);
+                }
+            }
+
+            private static bool IsDisposed(object target)
+            {
+                if (target == null) return true;
+
+                if (target is BaseHandle basehandle) return basehandle.Disposed || basehandle.IsDisposeQueued;
+
+                if (target is Disposable disposable) return disposable.Disposed || disposable.IsDisposeQueued;
+
+                return false;
+            }
+
+            public bool Equals(U handler)
+            {
+                Delegate other = (Delegate)(object)handler;
+                bool isOtherStatic = other.Target == null;
+                return (isOtherStatic || weakTarget?.Target == other.Target) && methodInfo.Equals(other.Method);
+            }
+
+            public void Invoke(params object[] args)
+            {
+                if (IsStatic)
+                {
+                    Delegate.CreateDelegate(typeof(U), methodInfo).DynamicInvoke(args);
+                }
+                else
+                {
+                    // Because GC is done in other thread,
+                    // it needs to check again that the reference is still alive before calling method.
+                    // To do that, the reference should be assigned to the local variable first.
+                    var rooting = weakTarget.Target;
+
+                    if (IsAlive)
+                    {
+                        Delegate.CreateDelegate(typeof(U), rooting, methodInfo).DynamicInvoke(args);
+                    }
+                }
+            }
+        }
+    }
+}