1+ using System . Buffers ;
2+
13using ColumnizerLib ;
24
35using NLog ;
@@ -8,29 +10,33 @@ public class LogBuffer
810{
911 #region Fields
1012
13+ private SpinLock _contentLock = new ( enableThreadOwnerTracking : false ) ;
1114 private static readonly Logger _logger = LogManager . GetCurrentClassLogger ( ) ;
1215
1316#if DEBUG
14- private readonly IList < long > _filePositions = [ ] ; // file position for every line
17+ private readonly List < long > _filePositions ; // file position for every line
1518#endif
1619
17- private readonly List < ILogLineMemory > _lineList = [ ] ;
20+ private LogLine [ ] _lineArray ;
21+ private int _lineArrayLength ; // capacity of the rented array
1822
1923 private int MAX_LINES = 500 ;
20- private long _size ;
2124
2225 #endregion
2326
2427 #region cTor
2528
26- //public LogBuffer() { }
27-
2829 // Don't use a primary constructor here: field initializers (like MAX_LINES) run before primary constructor parameters are assigned,
2930 // so MAX_LINES would always be set to its default value before the constructor body can assign it. Use a regular constructor instead.
3031 public LogBuffer ( ILogFileInfo fileInfo , int maxLines )
3132 {
3233 FileInfo = fileInfo ;
3334 MAX_LINES = maxLines ;
35+ _lineArray = ArrayPool < LogLine > . Shared . Rent ( maxLines ) ;
36+ _lineArrayLength = _lineArray . Length ;
37+ #if DEBUG
38+ _filePositions = new ( MAX_LINES ) ;
39+ #endif
3440 }
3541
3642 #endregion
@@ -43,18 +49,18 @@ public long Size
4349 {
4450 set
4551 {
46- _size = value ;
52+ field = value ;
4753#if DEBUG
4854 if ( _filePositions . Count > 0 )
4955 {
50- if ( _size < _filePositions [ _filePositions . Count - 1 ] - StartPos )
56+ if ( field < _filePositions [ ^ 1 ] - StartPos )
5157 {
5258 _logger . Error ( "LogBuffer overall Size must be greater than last line file position!" ) ;
5359 }
5460 }
5561#endif
5662 }
57- get => _size ;
63+ get ;
5864 }
5965
6066 public int EndLine => StartLine + LineCount ;
@@ -75,36 +81,91 @@ public long Size
7581
7682 #region Public methods
7783
78- public void AddLine ( ILogLineMemory lineMemory , long filePos )
84+ public void AddLine ( LogLine lineMemory , long filePos )
7985 {
80- _lineList . Add ( lineMemory ) ;
86+ if ( LineCount < _lineArrayLength )
87+ {
88+ _lineArray [ LineCount ] = lineMemory ;
89+ LineCount ++ ;
90+ }
91+ #if DEBUG
92+ else
93+ {
94+ _logger . Error ( "AddLine overflow: LineCount={0} >= _lineArrayLength={1}" , LineCount , _lineArrayLength ) ;
95+ }
96+ #endif
97+
8198#if DEBUG
8299 _filePositions . Add ( filePos ) ;
83100#endif
84- LineCount ++ ;
85101 IsDisposed = false ;
86102 }
87103
88104 public void ClearLines ( )
89105 {
90- _lineList . Clear ( ) ;
106+ Array . Clear ( _lineArray , 0 , LineCount ) ;
91107 LineCount = 0 ;
92108 }
93109
110+ /// <summary>
111+ /// Prepares the buffer for reuse from the pool.
112+ /// </summary>
113+ public void Reinitialise ( ILogFileInfo fileInfo , int maxLines )
114+ {
115+ FileInfo = fileInfo ;
116+ MAX_LINES = maxLines ;
117+ StartLine = 0 ;
118+ StartPos = 0 ;
119+ Size = 0 ;
120+ LineCount = 0 ;
121+ DroppedLinesCount = 0 ;
122+ PrevBuffersDroppedLinesSum = 0 ;
123+ IsDisposed = false ;
124+ _lineArray = ArrayPool < LogLine > . Shared . Rent ( maxLines ) ;
125+ _lineArrayLength = _lineArray . Length ;
126+ #if DEBUG
127+ _filePositions . Clear ( ) ;
128+ DisposeCount = 0 ;
129+ #endif
130+ }
131+
94132 public void DisposeContent ( )
95133 {
96- _lineList . Clear ( ) ;
134+ if ( _lineArray != null )
135+ {
136+ Array . Clear ( _lineArray , 0 , LineCount ) ;
137+ ArrayPool < LogLine > . Shared . Return ( _lineArray ) ;
138+ _lineArray = null ;
139+ LineCount = 0 ;
140+ }
141+
97142 IsDisposed = true ;
98143#if DEBUG
99144 DisposeCount ++ ;
100145#endif
101146 }
102147
103- public ILogLineMemory GetLineMemoryOfBlock ( int num )
148+ public LogLine ? GetLineMemoryOfBlock ( int num )
149+ {
150+ return num < LineCount && num >= 0
151+ ? _lineArray [ num ]
152+ : null ;
153+ }
154+
155+ /// <summary>
156+ /// Acquires the content lock. The caller MUST call <see cref="ReleaseContentLock"/> in a finally block.
157+ /// </summary>
158+ public void AcquireContentLock ( ref bool lockTaken )
159+ {
160+ _contentLock . Enter ( ref lockTaken ) ;
161+ }
162+
163+ /// <summary>
164+ /// Releases the content lock previously acquired via <see cref="AcquireContentLock"/>.
165+ /// </summary>
166+ public void ReleaseContentLock ( )
104167 {
105- return num < _lineList . Count && num >= 0
106- ? _lineList [ num ]
107- : null ;
168+ _contentLock . Exit ( useMemoryBarrier : false ) ;
108169 }
109170
110171 #endregion
0 commit comments