Skip to content

Commit da442dc

Browse files
authored
Merge pull request #1 from mrdav30/develop
Improved overall stability and predictability in multi-threaded environments.
2 parents ce5dc16 + 6e2bfc8 commit da442dc

File tree

2 files changed

+39
-10
lines changed

2 files changed

+39
-10
lines changed

src/SwiftCollections/Pool/DefaultImplementations/SwiftArrayPool.cs

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ namespace SwiftCollections.Pool
2727
/// <summary>
2828
/// Tracks whether the pool has been disposed.
2929
/// </summary>
30-
private bool _disposed;
30+
private volatile bool _disposed;
3131

3232
#endregion
3333

@@ -165,10 +165,15 @@ public void Dispose()
165165

166166
private void OnDispose()
167167
{
168-
if (_disposed) return;
168+
if (_disposed)
169+
return;
169170

170-
Clear();
171171
_disposed = true;
172+
173+
foreach (var pool in _sizePools.Values)
174+
pool.Dispose();
175+
176+
_sizePools.Clear();
172177
}
173178

174179
~SwiftArrayPool() => OnDispose(); // Called by GC if Dispose() wasn't called explicitly.

src/SwiftCollections/Pool/SwiftObjectPool.cs

Lines changed: 31 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,15 @@ public sealed class SwiftObjectPool<T> : IDisposable, ISwiftObjectPool<T> where
1313
{
1414
#region Fields
1515

16-
private readonly ConcurrentBag<T> _pool;
16+
private readonly ConcurrentStack<T> _pool;
1717
private readonly Func<T> _createFunc;
1818
private readonly Action<T> _actionOnGet;
1919
private readonly Action<T> _actionOnRelease;
2020
private readonly Action<T> _actionOnDestroy;
2121
private readonly int _maxSize;
2222

23+
private volatile bool _disposed;
24+
2325
#endregion
2426

2527
#region Constructor
@@ -44,7 +46,7 @@ public SwiftObjectPool(
4446
if (createFunc == null) ThrowHelper.ThrowArgumentNullException(nameof(createFunc));
4547
if (maxSize <= 0) ThrowHelper.ThrowArgumentException($"{nameof(maxSize)} must be greater than 0");
4648

47-
_pool = new ConcurrentBag<T>();
49+
_pool = new ConcurrentStack<T>();
4850
_createFunc = createFunc;
4951
_actionOnGet = actionOnGet;
5052
_actionOnRelease = actionOnRelease;
@@ -83,7 +85,7 @@ public SwiftObjectPool(
8385
[MethodImpl(MethodImplOptions.AggressiveInlining)]
8486
public T Rent()
8587
{
86-
if (_pool.TryTake(out var obj))
88+
if (_pool.TryPop(out var obj))
8789
{
8890
_actionOnGet?.Invoke(obj);
8991
return obj;
@@ -118,7 +120,7 @@ public void Release(T element)
118120
_actionOnRelease?.Invoke(element);
119121

120122
if (_pool.Count < _maxSize)
121-
_pool.Add(element);
123+
_pool.Push(element);
122124
else
123125
{
124126
_actionOnDestroy?.Invoke(element);
@@ -131,7 +133,10 @@ public void Release(T element)
131133
/// </summary>
132134
public void Clear()
133135
{
134-
while (_pool.TryTake(out var obj))
136+
if (_disposed)
137+
return;
138+
139+
while (_pool.TryPop(out var obj))
135140
_actionOnDestroy?.Invoke(obj);
136141

137142
CountAll = 0;
@@ -141,8 +146,27 @@ public void Clear()
141146

142147
#region IDisposable Implementation
143148

144-
[MethodImpl(MethodImplOptions.AggressiveInlining)]
145-
public void Dispose() => Clear();
149+
/// <summary>
150+
/// Releases all resources used by the SwiftArrayPool.
151+
/// It is important to call Dispose() to release pooled arrays, preventing potential memory leaks.
152+
/// </summary>
153+
public void Dispose()
154+
{
155+
OnDispose();
156+
GC.SuppressFinalize(this); // Avoids calling the finalizer if already disposed.
157+
}
158+
159+
private void OnDispose()
160+
{
161+
if (_disposed)
162+
return;
163+
164+
_disposed = true;
165+
166+
_pool.Clear();
167+
}
168+
169+
~SwiftObjectPool() => OnDispose(); // Called by GC if Dispose() wasn't called explicitly.
146170

147171
#endregion
148172
}

0 commit comments

Comments
 (0)