diff options
Diffstat (limited to 'lib/Plugins.Runtime')
-rw-r--r-- | lib/Plugins.Runtime/src/LoaderExtensions.cs | 18 | ||||
-rw-r--r-- | lib/Plugins.Runtime/src/PluginController.cs | 30 | ||||
-rw-r--r-- | lib/Plugins.Runtime/src/RuntimePluginLoader.cs | 19 | ||||
-rw-r--r-- | lib/Plugins.Runtime/src/Services/PluginServiceExport.cs | 20 |
4 files changed, 42 insertions, 45 deletions
diff --git a/lib/Plugins.Runtime/src/LoaderExtensions.cs b/lib/Plugins.Runtime/src/LoaderExtensions.cs index e88ccb3..5ffbecb 100644 --- a/lib/Plugins.Runtime/src/LoaderExtensions.cs +++ b/lib/Plugins.Runtime/src/LoaderExtensions.cs @@ -250,7 +250,7 @@ namespace VNLib.Plugins.Runtime /// <exception cref="AggregateException"></exception> public static void InvokeUnload(this IPluginStack runtime) { - _ = runtime ?? throw new ArgumentNullException(nameof(runtime)); + ArgumentNullException.ThrowIfNull(runtime); //try unloading all plugins runtime.Plugins.TryForeach(static p => p.UnloadPlugins()); @@ -265,10 +265,14 @@ namespace VNLib.Plugins.Runtime /// <exception cref="AggregateException"></exception> public static void UnloadAll(this IPluginStack runtime) { - _ = runtime ?? throw new ArgumentNullException(nameof(runtime)); + ArgumentNullException.ThrowIfNull(runtime); - //try unloading all plugins and their loaders - runtime.Plugins.TryForeach(static p => p.UnloadAll()); + //try unloading all plugins and their loaders, dont invoke GC on each unload + runtime.Plugins.TryForeach(static p => p.UnloadAll(false)); + + //Invoke a gc + GC.Collect(); + GC.WaitForPendingFinalizers(); } /// <summary> @@ -282,7 +286,11 @@ namespace VNLib.Plugins.Runtime ArgumentNullException.ThrowIfNull(runtime, nameof(runtime)); //try reloading all plugins - runtime.Plugins.TryForeach(static p => p.ReloadPlugins()); + runtime.Plugins.TryForeach(static p => p.ReloadPlugins(false)); + + //Invoke a gc + GC.Collect(); + GC.WaitForPendingFinalizers(); } /// <summary> diff --git a/lib/Plugins.Runtime/src/PluginController.cs b/lib/Plugins.Runtime/src/PluginController.cs index 7f82c13..3879060 100644 --- a/lib/Plugins.Runtime/src/PluginController.cs +++ b/lib/Plugins.Runtime/src/PluginController.cs @@ -52,17 +52,9 @@ namespace VNLib.Plugins.Runtime */ private readonly object _stateLock = new(); - private readonly List<LivePlugin> _plugins; - private readonly List<KeyValuePair<IPluginEventListener, object?>> _listeners; - private readonly PluginServicePool _servicePool; - - - internal PluginController() - { - _plugins = new (); - _listeners = new (); - _servicePool = new (); - } + private readonly List<LivePlugin> _plugins = []; + private readonly List<KeyValuePair<IPluginEventListener, object?>> _listeners = []; + private readonly PluginServicePool _servicePool = new(); /// <summary> /// The current collection of plugins. Valid before the unload event. @@ -73,7 +65,7 @@ namespace VNLib.Plugins.Runtime ///<exception cref="ArgumentNullException"></exception> public void Register(IPluginEventListener listener, object? state = null) { - _ = listener ?? throw new ArgumentNullException(nameof(listener)); + ArgumentNullException.ThrowIfNull(listener); lock (_stateLock) { @@ -87,12 +79,12 @@ namespace VNLib.Plugins.Runtime lock(_stateLock) { //Remove listener - return _listeners.RemoveAll(p => p.Key == listener) > 0; + return _listeners.RemoveAll(p => ReferenceEquals(p.Key, listener)) > 0; } } /// <summary> - /// Populates the given <see cref="IServiceContainer"/> with all services + /// Returns an array of all exported services from all loaded plugins /// </summary> public PluginServiceExport[] GetExportedServices() => _servicePool.GetServices(); @@ -118,8 +110,8 @@ namespace VNLib.Plugins.Runtime { lock (_stateLock) { - _plugins.TryForeach(lp => lp.InitConfig(configData.AsSpan())); - _plugins.TryForeach(lp => lp.InitLog(cliArgs)); + _plugins.ForEach(lp => lp.InitConfig(configData.AsSpan())); + _plugins.ForEach(lp => lp.InitLog(cliArgs)); } } @@ -131,10 +123,10 @@ namespace VNLib.Plugins.Runtime _plugins.TryForeach(static p => p.LoadPlugin()); //Load all services into the service pool - _plugins.TryForeach(p => p.GetServices(_servicePool)); + _plugins.ForEach(p => p.GetServices(_servicePool)); //Notify event handlers - _listeners.TryForeach(l => l.Key.OnPluginLoaded(this, l.Value)); + _listeners.ForEach(l => l.Key.OnPluginLoaded(this, l.Value)); } } @@ -145,7 +137,7 @@ namespace VNLib.Plugins.Runtime try { //Notify event handlers - _listeners.TryForeach(l => l.Key.OnPluginUnloaded(this, l.Value)); + _listeners.ForEach(l => l.Key.OnPluginUnloaded(this, l.Value)); //Unload plugin instances _plugins.TryForeach(static p => p.UnloadPlugin()); diff --git a/lib/Plugins.Runtime/src/RuntimePluginLoader.cs b/lib/Plugins.Runtime/src/RuntimePluginLoader.cs index 40cf5ed..60edf55 100644 --- a/lib/Plugins.Runtime/src/RuntimePluginLoader.cs +++ b/lib/Plugins.Runtime/src/RuntimePluginLoader.cs @@ -119,18 +119,19 @@ namespace VNLib.Plugins.Runtime /// Manually reload the internal <see cref="IPluginAssemblyLoader"/> /// which will reload the assembly and re-initialize the controller /// </summary> + /// <param name="forceGc">A value that indicates if the current unload should cause a manual garbage collection</param> /// <exception cref="AggregateException"></exception> /// <exception cref="NotSupportedException"></exception> - public void ReloadPlugins() + public void ReloadPlugins(bool forceGc) { //Not unloadable - if (!Loader.Config.Unloadable) + if (!Config.Unloadable) { throw new NotSupportedException("The loading context is not unloadable, you may not dynamically reload plugins"); } - + //All plugins must be unloaded first - UnloadPlugins(); + UnloadAll(forceGc); //Reload the assembly and InitializeController(); @@ -152,8 +153,9 @@ namespace VNLib.Plugins.Runtime /// then attempts to unload the <see cref="IPluginAssemblyLoader"/> if dynamic unloading /// is enabled, otherwise does nothing. /// </summary> + /// <param name="forceGc">A value that indicates if the current unload should cause a manual garbage collection</param> /// <exception cref="AggregateException"></exception> - public void UnloadAll() + public void UnloadAll(bool forceGc) { UnloadPlugins(); @@ -162,6 +164,13 @@ namespace VNLib.Plugins.Runtime { Loader.Unload(); } + + //Optionally wait for GC to finish + if (forceGc) + { + GC.Collect(); + GC.WaitForPendingFinalizers(); + } } //Process unload events diff --git a/lib/Plugins.Runtime/src/Services/PluginServiceExport.cs b/lib/Plugins.Runtime/src/Services/PluginServiceExport.cs index 0053a70..acacbb6 100644 --- a/lib/Plugins.Runtime/src/Services/PluginServiceExport.cs +++ b/lib/Plugins.Runtime/src/Services/PluginServiceExport.cs @@ -29,21 +29,9 @@ namespace VNLib.Plugins.Runtime.Services /// <summary> /// An immutable wrapper for an exported service by an <see cref="IPlugin"/> /// </summary> - public readonly record struct PluginServiceExport - { - /// <summary> - /// The exported service type - /// </summary> - public readonly Type ServiceType { get; init; } + /// <param name="Flags">The export flags</param> + /// <param name="Service">The exported service instance</param> + /// <param name="ServiceType">The exported service type</param> + public readonly record struct PluginServiceExport(Type ServiceType, object Service, ExportFlags Flags); - /// <summary> - /// The exported service instance - /// </summary> - public readonly object Service { get; init; } - - /// <summary> - /// The export flags - /// </summary> - public readonly ExportFlags Flags { get; init; } - } } |