1+ using System . Collections . Concurrent ;
2+
13namespace ModularPipelines . Logging ;
24
35/// <summary>
@@ -8,29 +10,24 @@ namespace ModularPipelines.Logging;
810/// This container tracks all module loggers created during pipeline execution
911/// and ensures they are properly flushed and disposed in the correct order
1012/// (ordered by last log written time) to maintain logical output ordering.
13+ /// Uses ConcurrentBag for lock-free thread-safe operations during high-concurrency
14+ /// module execution.
1115/// </remarks>
1216internal class ModuleLoggerContainer : IModuleLoggerContainer , IDisposable
1317{
14- private readonly List < ModuleLogger > _loggers = new ( ) ;
15- private bool _isDisposed ;
18+ private readonly ConcurrentBag < ModuleLogger > _loggers = new ( ) ;
19+ private int _isDisposed ;
1620
1721 public void FlushAndDisposeAll ( )
1822 {
19- lock ( _loggers )
23+ // Use Interlocked to ensure only one thread disposes
24+ if ( Interlocked . Exchange ( ref _isDisposed , 1 ) == 1 )
2025 {
21- if ( _isDisposed )
22- {
23- return ;
24- }
25-
26- _isDisposed = true ;
26+ return ;
2727 }
2828
29- List < ModuleLogger > snapshot ;
30- lock ( _loggers )
31- {
32- snapshot = _loggers . ToList ( ) ;
33- }
29+ // ToArray() is thread-safe on ConcurrentBag
30+ var snapshot = _loggers . ToArray ( ) ;
3431
3532 foreach ( var logger in snapshot . Where ( x => x != null ) . OrderBy ( x => x . LastLogWritten ) )
3633 {
@@ -40,22 +37,18 @@ public void FlushAndDisposeAll()
4037
4138 public IModuleLogger ? GetLogger ( Type type )
4239 {
43- lock ( _loggers )
44- {
45- return _loggers . FirstOrDefault ( logger => logger . GetType ( ) == type ) ;
46- }
40+ // ToArray() creates a snapshot for safe enumeration
41+ return _loggers . ToArray ( ) . FirstOrDefault ( logger => logger . GetType ( ) == type ) ;
4742 }
4843
4944 public void AddLogger ( ModuleLogger logger )
5045 {
51- lock ( _loggers )
52- {
53- _loggers . Add ( logger ) ;
54- }
46+ // ConcurrentBag.Add is lock-free and thread-safe
47+ _loggers . Add ( logger ) ;
5548 }
5649
5750 public void Dispose ( )
5851 {
5952 FlushAndDisposeAll ( ) ;
6053 }
61- }
54+ }
0 commit comments