From 26a0ebc027fcfa0294812fee4090c6843b8e17d2 Mon Sep 17 00:00:00 2001 From: Tolik Pylypchuk Date: Mon, 18 Sep 2023 22:14:54 +0300 Subject: [PATCH] Add a better way to register a log source --- SharpHook.Sample/Program.cs | 2 +- SharpHook/Logging/LogSource.cs | 75 +++++++++++++++++++++++++++++++--- SharpHook/SharpHook.xml | 41 +++++++++++++++++-- 3 files changed, 108 insertions(+), 10 deletions(-) diff --git a/SharpHook.Sample/Program.cs b/SharpHook.Sample/Program.cs index 591cedee..ba1f6421 100644 --- a/SharpHook.Sample/Program.cs +++ b/SharpHook.Sample/Program.cs @@ -2,7 +2,7 @@ Console.WriteLine("---------- SharpHook Sample ----------\n"); -using var logSource = LogSource.Register(minLevel: LogLevel.Debug); +using var logSource = LogSource.RegisterOrGet(minLevel: LogLevel.Debug); using var reactiveLogSource = new ReactiveLogSourceAdapter(logSource, TaskPoolScheduler.Default); reactiveLogSource.MessageLogged.Subscribe(OnMessageLogged); diff --git a/SharpHook/Logging/LogSource.cs b/SharpHook/Logging/LogSource.cs index 04fb6998..36f6de79 100644 --- a/SharpHook/Logging/LogSource.cs +++ b/SharpHook/Logging/LogSource.cs @@ -19,6 +19,10 @@ namespace SharpHook.Logging; [ExcludeFromCodeCoverage] public sealed class LogSource : ILogSource { + private static readonly object syncRoot = new(); + + private static LogSource? registeredLogSource = null; + private readonly LogEntryParser parser; private readonly LoggerProc loggerProc; private readonly ILoggingProvider loggingProvider; @@ -52,15 +56,66 @@ private LogSource(ILoggingProvider loggingProvider, LogEntryParser parser, LogLe /// public bool IsDisposed { get; private set; } = false; + /// + /// Creates and registers a source of libuiohook logs or returns the registered instance. + /// + /// The minimum log level. + /// A source of libuiohook logs. + /// + /// This method should be preferred to as it's safer - it won't invalidate an + /// already registered instance. + /// + public static LogSource RegisterOrGet(LogLevel minLevel = LogLevel.Info) => + RegisterOrGet(UioHookProvider.Instance, minLevel); + + /// + /// Creates and registers a source of libuiohook logs or returns the registered instance. + /// + /// The logging provider used to register the log source. + /// The minimum log level. + /// A source of libuiohook logs. + /// + /// + /// This method should be preferred to as it's safer - it won't invalidate an + /// already registered instance. + /// + /// + /// A single instance of can be registered using this method, irrespective of the logging + /// provider used. + /// + /// + /// + /// is . + /// + public static LogSource RegisterOrGet(ILoggingProvider loggingProvider, LogLevel minLevel = LogLevel.Info) + { + if (loggingProvider is null) + { + throw new ArgumentNullException(nameof(loggingProvider)); + } + + lock (syncRoot) + { + if (registeredLogSource is null) + { + registeredLogSource = new LogSource(loggingProvider, LogEntryParser.Instance, minLevel); + loggingProvider.SetLoggerProc(registeredLogSource.loggerProc, IntPtr.Zero); + } + + return registeredLogSource; + } + } + /// /// Creates and registers a source of libuiohook logs. /// /// The minimum log level. /// A source of libuiohook logs. /// - /// This method must not be called when another instance has already been registerd and - /// hasn't been disposed. + /// This method is obsolete as it must not be called when another instance has already been + /// registerd and hasn't been disposed. should be used instead. /// + [Obsolete("LogSource.RegisterOrGet should be used instead")] public static LogSource Register(LogLevel minLevel = LogLevel.Info) => Register(UioHookProvider.Instance, minLevel); @@ -71,12 +126,14 @@ public static LogSource Register(LogLevel minLevel = LogLevel.Info) => /// The minimum log level. /// A source of libuiohook logs. /// - /// This method must not be called when another instance has already been registerd and - /// hasn't been disposed. + /// This method is obsolete as it must not be called when another instance has already been + /// registerd and hasn't been disposed. should be used + /// instead. /// /// /// is . /// + [Obsolete("LogSource.RegisterOrGet should be used instead")] public static LogSource Register(ILoggingProvider loggingProvider, LogLevel minLevel = LogLevel.Info) { if (loggingProvider is null) @@ -105,7 +162,15 @@ private void Dispose(bool disposing) return; } - this.loggingProvider.SetLoggerProc(null, IntPtr.Zero); + lock (syncRoot) + { + if (registeredLogSource == this) + { + registeredLogSource = null; + } + + this.loggingProvider.SetLoggerProc(null, IntPtr.Zero); + } if (disposing) { diff --git a/SharpHook/SharpHook.xml b/SharpHook/SharpHook.xml index e53b8ee4..952727c6 100644 --- a/SharpHook/SharpHook.xml +++ b/SharpHook/SharpHook.xml @@ -1082,6 +1082,38 @@ A disposed log source doesn't raise the event and cannot be registered again. + + + Creates and registers a source of libuiohook logs or returns the registered instance. + + The minimum log level. + A source of libuiohook logs. + + This method should be preferred to as it's safer - it won't invalidate an + already registered instance. + + + + + Creates and registers a source of libuiohook logs or returns the registered instance. + + The logging provider used to register the log source. + The minimum log level. + A source of libuiohook logs. + + + This method should be preferred to as it's safer - it won't invalidate an + already registered instance. + + + A single instance of can be registered using this method, irrespective of the logging + provider used. + + + + is . + + Creates and registers a source of libuiohook logs. @@ -1089,8 +1121,8 @@ The minimum log level. A source of libuiohook logs. - This method must not be called when another instance has already been registerd and - hasn't been disposed. + This method is obsolete as it must not be called when another instance has already been + registerd and hasn't been disposed. should be used instead. @@ -1101,8 +1133,9 @@ The minimum log level. A source of libuiohook logs. - This method must not be called when another instance has already been registerd and - hasn't been disposed. + This method is obsolete as it must not be called when another instance has already been + registerd and hasn't been disposed. should be used + instead. is .