From: Hwankyu Jhun Date: Wed, 14 May 2025 04:51:02 +0000 (+0900) Subject: [NUI.Gadget] Consider thread safe X-Git-Tag: submit/tizen/20250514.150937~1^2~2 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=06634b42bbbe2a4c483ee4069fa638f423d935e1;p=platform%2Fcore%2Fcsapi%2Ftizenfx.git [NUI.Gadget] Consider thread safe To prevent thread safe issues, this patch changes container types to ConcurrentDictionary. Signed-off-by: Hwankyu Jhun --- diff --git a/src/Tizen.NUI.Gadget/Interop/Interop.Libc.cs b/src/Tizen.NUI.Gadget/Interop/Interop.Libc.cs index ef361ad08..eabbd0163 100755 --- a/src/Tizen.NUI.Gadget/Interop/Interop.Libc.cs +++ b/src/Tizen.NUI.Gadget/Interop/Interop.Libc.cs @@ -22,6 +22,6 @@ internal static partial class Interop internal static partial class Libc { [DllImport(Libraries.Libc, EntryPoint = "getenv")] - internal static extern IntPtr GetEnviornmentVariable(string name); + internal static extern IntPtr GetEnvironmentVariable(string name); } } diff --git a/src/Tizen.NUI.Gadget/Tizen.NUI/NUIGadgetManager.cs b/src/Tizen.NUI.Gadget/Tizen.NUI/NUIGadgetManager.cs index 2d3f2de87..edb3518c3 100755 --- a/src/Tizen.NUI.Gadget/Tizen.NUI/NUIGadgetManager.cs +++ b/src/Tizen.NUI.Gadget/Tizen.NUI/NUIGadgetManager.cs @@ -15,16 +15,14 @@ */ using System; +using System.Collections.Concurrent; using System.Collections.Generic; -using System.Linq; using System.IO; -using Tizen.Applications; -using System.ComponentModel; +using System.Linq; using System.Runtime.InteropServices; -using System.Runtime.Loader; using System.Reflection; -using System.Threading.Tasks; -using System.Security.AccessControl; +using Tizen.Applications; +using System.ComponentModel; using SystemIO = System.IO; @@ -37,73 +35,49 @@ namespace Tizen.NUI [EditorBrowsable(EditorBrowsableState.Never)] public static class NUIGadgetManager { - private static readonly Dictionary _gadgetInfos = new Dictionary(); - private static readonly List _gadgets = new List(); + private static readonly ConcurrentDictionary _gadgetInfos = new ConcurrentDictionary(StringComparer.Ordinal); + private static readonly ConcurrentDictionary _gadgets = new ConcurrentDictionary(); static NUIGadgetManager() { - IntPtr gadgetPkgIds = Interop.Libc.GetEnviornmentVariable("GADGET_PKGIDS"); - if (gadgetPkgIds != IntPtr.Zero) + var ptr = Interop.Libc.GetEnvironmentVariable("GADGET_PKGIDS"); + if (ptr != IntPtr.Zero) { - string packages = Marshal.PtrToStringAnsi(gadgetPkgIds); - if (string.IsNullOrEmpty(packages)) - { - Log.Warn("There is no resource packages"); - } - else + var packages = Marshal.PtrToStringAnsi(ptr); + if (!string.IsNullOrWhiteSpace(packages)) { - foreach (string packageId in packages.Split(':').ToList()) + foreach (var pkg in packages.Split(':')) { - NUIGadgetInfo info = NUIGadgetInfo.CreateNUIGadgetInfo(packageId); + var info = NUIGadgetInfo.CreateNUIGadgetInfo(pkg); if (info != null) { - _gadgetInfos.Add(info.ResourceType, info); + try + { + _gadgetInfos.TryAdd(info.ResourceType, info); + } + catch (Exception e) when (e is ArgumentNullException || e is OverflowException) + { + Log.Error("Exception occurs. " + e.Message); + } } } } + else + { + Log.Warn("No gadget packages found."); + } } else { - Log.Warn("Failed to get environment variable"); + Log.Warn("GADGET_PKGIDS not set."); } - var context = (CoreApplication)CoreApplication.Current; - context.AppControlReceived += OnAppControlReceived; - context.LowMemory += OnLowMemory; - context.LowBattery += OnLowBattery; - context.LocaleChanged += OnLocaleChanged; - context.RegionFormatChanged += OnRegionFormatChanged; - context.DeviceOrientationChanged += OnDeviceOrientationChanged; - } - - private static void OnAppControlReceived(object sender, AppControlReceivedEventArgs args) - { - HandleAppControl(args); - } - - private static void OnLowMemory(object sender, LowMemoryEventArgs args) - { - HandleEvents(NUIGadgetEventType.LowMemory, args); - } - - private static void OnLowBattery(object sender, LowBatteryEventArgs args) - { - HandleEvents(NUIGadgetEventType.LowBattery, args); - } - - private static void OnLocaleChanged(object sender, LocaleChangedEventArgs args) - { - HandleEvents(NUIGadgetEventType.LocaleChanged, args); - } - - private static void OnRegionFormatChanged(object sender, RegionFormatChangedEventArgs args) - { - HandleEvents(NUIGadgetEventType.RegionFormatChanged, args); - } - - private static void OnDeviceOrientationChanged(object sender, DeviceOrientationEventArgs args) - { - HandleEvents(NUIGadgetEventType.DeviceORientationChanged, args); + var app = (CoreApplication)CoreApplication.Current; + app.AppControlReceived += (s, e) => HandleAppControl(e); + app.LowMemory += (s, e) => HandleEvents(NUIGadgetEventType.LowMemory, e); + app.LowBattery += (s, e) => HandleEvents(NUIGadgetEventType.LowBattery, e); + app.LocaleChanged += (s, e) => HandleEvents(NUIGadgetEventType.LocaleChanged, e); + app.RegionFormatChanged += (s, e) => HandleEvents(NUIGadgetEventType.RegionFormatChanged, e); } /// @@ -123,13 +97,13 @@ namespace Tizen.NUI if (args.State == NUIGadgetLifecycleState.Destroyed) { args.Gadget.LifecycleChanged -= OnNUIGadgetLifecycleChanged; - _gadgets.Remove(args.Gadget); + _gadgets.TryRemove(args.Gadget, out _); } } private static NUIGadgetInfo Find(string resourceType) { - if (!_gadgetInfos.TryGetValue(resourceType, out NUIGadgetInfo info)) + if (!_gadgetInfos.TryGetValue(resourceType, out var info)) { throw new ArgumentException("Failed to find NUIGadgetInfo. resource type: " + resourceType); } @@ -148,10 +122,7 @@ namespace Tizen.NUI /// Thrown when failed because of a invalid argument. /// Thrown when failed because of an invalid operation. /// 10 - public static void Load(string resourceType) - { - Load(resourceType, true); - } + public static void Load(string resourceType) => Load(resourceType, true); /// /// Loads an assembly of the NUIGadget. @@ -169,60 +140,14 @@ namespace Tizen.NUI } NUIGadgetInfo info = Find(resourceType); - Load(info, useDefaultContext); - } - - /// - /// Unloads the specified NUIGadget assembly from memory. - /// - /// - /// To use this method properly, the assembly of the gadget must be loaded using Load() with the custom context. - /// - /// The resource type of the NUIGadget package to unload. - /// Thrown when the argument passed is not valid. - /// - /// - /// /// Load an assembly of the NUIGadget. - /// NUIGadgetManager.Load("org.tizen.appfw.gadget.NetworkSetting", false); - /// /// NUIGadgetManager.Add("org.tizen.appfw.gadget.NetworkSetting", "NetworkSettingGadget", false); - /// - /// /// Unload the loaded assembly - /// NUIGadgetManager.Unload("org.tizen.appfw.gadget.NetworkSetting"); - /// - /// - /// 10 - public static void Unload(string resourceType) - { - if (string.IsNullOrEmpty(resourceType)) - { - throw new ArgumentException("Invalid argument"); - } - - NUIGadgetInfo info = Find(resourceType); - Unload(info); + LoadInternal(info, useDefaultContext); } - private static void Unload(NUIGadgetInfo info) + private static void LoadInternal(NUIGadgetInfo info, bool useDefaultContext) { if (info == null) { - throw new ArgumentException("Invalid argument"); - } - - lock (info) - { - if (info.NUIGadgetAssembly != null && info.NUIGadgetAssembly.IsLoaded) - { - info.NUIGadgetAssembly.Unload(); - } - } - } - - private static void Load(NUIGadgetInfo info, bool useDefaultContext) - { - if (info == null) - { - throw new ArgumentException("Invalid argument"); + throw new ArgumentException("Invalid argument", nameof(info)); } try @@ -251,13 +176,50 @@ namespace Tizen.NUI } } } - catch (FileLoadException e) + catch (Exception e) when (e is FileLoadException || e is BadImageFormatException) { - throw new InvalidOperationException(e.Message); + throw new InvalidOperationException(e.Message, e); } - catch (BadImageFormatException e) + } + + /// + /// Unloads the specified NUIGadget assembly from memory. + /// + /// + /// To use this method properly, the assembly of the gadget must be loaded using Load() with the custom context. + /// + /// The resource type of the NUIGadget package to unload. + /// Thrown when the argument passed is not valid. + /// + /// + /// /// Load an assembly of the NUIGadget. + /// NUIGadgetManager.Load("org.tizen.appfw.gadget.NetworkSetting", false); + /// /// NUIGadgetManager.Add("org.tizen.appfw.gadget.NetworkSetting", "NetworkSettingGadget", false); + /// + /// /// Unload the loaded assembly + /// NUIGadgetManager.Unload("org.tizen.appfw.gadget.NetworkSetting"); + /// + /// + /// 10 + public static void Unload(string resourceType) + { + if (string.IsNullOrWhiteSpace(resourceType)) + { + throw new ArgumentException("Invalid argument", nameof(resourceType)); + } + + NUIGadgetInfo info = Find(resourceType); + if (info == null) + { + throw new ArgumentException("Invalid argument", nameof(resourceType)); + } + + lock (info) { - throw new InvalidOperationException(e.Message); + if (info.NUIGadgetAssembly?.IsLoaded == true) + { + info.NUIGadgetAssembly.Unload(); + } } } @@ -270,10 +232,7 @@ namespace Tizen.NUI /// Thrown when failed because of a invalid argument. /// Thrown when failed because of an invalid operation. /// 10 - public static NUIGadget Add(string resourceType, string className) - { - return Add(resourceType, className, true); - } + public static NUIGadget Add(string resourceType, string className) => Add(resourceType, className, true); /// /// Adds a NUIGadget to the NUIGadgetManager. @@ -290,13 +249,13 @@ namespace Tizen.NUI /// 10 public static NUIGadget Add(string resourceType, string className, bool useDefaultContext) { - if (string.IsNullOrEmpty(resourceType) || string.IsNullOrEmpty(className)) + if (string.IsNullOrWhiteSpace(resourceType) || string.IsNullOrWhiteSpace(className)) { throw new ArgumentException("Invalid argument"); } NUIGadgetInfo info = Find(resourceType); - Load(info, useDefaultContext); + LoadInternal(info, useDefaultContext); NUIGadget gadget = useDefaultContext ? info.Assembly.CreateInstance(className, true) as NUIGadget : info.NUIGadgetAssembly.CreateInstance(className); if (gadget == null) @@ -313,7 +272,7 @@ namespace Tizen.NUI throw new InvalidOperationException("The View MUST be created"); } - _gadgets.Add(gadget); + _gadgets.TryAdd(gadget, 0); return gadget; } @@ -322,10 +281,7 @@ namespace Tizen.NUI /// /// An enumerable list containing all the active NUIGadgets. /// 10 - public static IEnumerable GetGadgets() - { - return _gadgets; - } + public static IEnumerable GetGadgets() => _gadgets.Keys; /// /// Retrieves information about available NUIGadgets. @@ -337,10 +293,7 @@ namespace Tizen.NUI /// /// An enumerable list of NUIGadgetInfo objects. /// 10 - public static IEnumerable GetGadgetInfos() - { - return _gadgetInfos.Values.ToList(); - } + public static IEnumerable GetGadgetInfos() => _gadgetInfos.Values; /// /// Removes the specified NUIGadget from the NUIGadgetManager. @@ -355,18 +308,14 @@ namespace Tizen.NUI /// 10 public static void Remove(NUIGadget gadget) { - if (gadget == null || !_gadgets.Contains(gadget)) + if (gadget == null || !_gadgets.ContainsKey(gadget) || gadget.State == NUIGadgetLifecycleState.Destroyed) { return; } - if (gadget.State == NUIGadgetLifecycleState.Destroyed) + _gadgets.TryRemove(gadget, out _); + CoreApplication.Post(() => { - return; - } - - _gadgets.Remove(gadget); - CoreApplication.Post(() => { Log.Warn("ResourceType: " + gadget.NUIGadgetInfo.ResourceType + ", State: " + gadget.State); gadget.Finish(); }); @@ -382,9 +331,9 @@ namespace Tizen.NUI /// 10 public static void RemoveAll() { - for (int i = _gadgets.Count - 1; i >= 0; i--) + foreach (var gadget in _gadgets.Keys.ToList()) { - Remove(_gadgets[i]); + Remove(gadget); } } @@ -416,7 +365,7 @@ namespace Tizen.NUI throw new ArgumentNullException(nameof(gadget)); } - if (!_gadgets.Contains(gadget)) + if (!_gadgets.ContainsKey(gadget)) { return; } @@ -444,7 +393,7 @@ namespace Tizen.NUI throw new ArgumentNullException(nameof(gadget)); } - if (!_gadgets.Contains(gadget)) + if (!_gadgets.ContainsKey(gadget)) { return; } @@ -471,9 +420,9 @@ namespace Tizen.NUI throw new ArgumentNullException(nameof(gadget)); } - if (!_gadgets.Contains(gadget)) + if (!_gadgets.ContainsKey(gadget)) { - throw new ArgumentException("Invalid argument"); + throw new ArgumentException("Invalid argument", nameof(gadget)); } if (appControl == null) @@ -487,13 +436,13 @@ namespace Tizen.NUI internal static bool HandleAppControl(AppControlReceivedEventArgs args) { var extraData = args.ReceivedAppControl?.ExtraData; - if (extraData == null||!extraData.TryGet("__K_GADGET_RES_TYPE", out string resourceType) || + if (extraData == null || !extraData.TryGet("__K_GADGET_RES_TYPE", out string resourceType) || !extraData.TryGet("__K_GADGET_CLASS_NAME", out string className)) { return false; } - foreach (NUIGadget gadget in _gadgets) + foreach (var gadget in _gadgets.Keys) { if (gadget.NUIGadgetInfo.ResourceType == resourceType && gadget.ClassName == className) { @@ -507,7 +456,7 @@ namespace Tizen.NUI internal static void HandleEvents(NUIGadgetEventType eventType, EventArgs args) { - foreach (NUIGadget gadget in _gadgets) + foreach (NUIGadget gadget in _gadgets.Keys) { gadget.HandleEvents(eventType, args); }