aboutsummaryrefslogtreecommitdiff
path: root/lib/Plugins.Runtime
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Plugins.Runtime')
-rw-r--r--lib/Plugins.Runtime/src/LoaderExtensions.cs18
-rw-r--r--lib/Plugins.Runtime/src/PluginController.cs30
-rw-r--r--lib/Plugins.Runtime/src/RuntimePluginLoader.cs19
-rw-r--r--lib/Plugins.Runtime/src/Services/PluginServiceExport.cs20
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; }
- }
}