Skip to content

Commit 23656b1

Browse files
author
Oren (electricessence)
committed
Added improved handlers.
1 parent c00a335 commit 23656b1

File tree

6 files changed

+72
-7
lines changed

6 files changed

+72
-7
lines changed

AsyncDisposeHandler.cs

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,22 @@ public AsyncDisposeHandler(Func<ValueTask> action)
1919
Func<ValueTask> _action;
2020

2121
protected override ValueTask OnDisposeAsync(AsyncDisposeMode mode)
22-
=> Interlocked.Exchange(ref _action, null).Invoke();
22+
=> Nullify(ref _action).Invoke();
23+
}
24+
25+
public class AsyncDisposeHandler<T> : AsyncDisposeHandler
26+
{
27+
public AsyncDisposeHandler(T value, Func<ValueTask> action) : base(action)
28+
{
29+
Value = value;
30+
}
31+
32+
public T Value { get; private set; }
33+
34+
protected override ValueTask OnDisposeAsync(AsyncDisposeMode mode)
35+
{
36+
Value = default;
37+
return base.OnDisposeAsync(mode);
38+
}
2339
}
2440
}

DisposableBase.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ public void Dispose()
3232
/// <param name="calledExplicitly">True if called through code in the runtime, or false if finalized by the garbage collector.</param>
3333
protected abstract void OnDispose(bool calledExplicitly);
3434

35-
protected bool StartDispose(bool calledExplicitly)
35+
internal protected bool StartDispose(bool calledExplicitly)
3636
{
3737
try
3838
{

DisposeHandler.cs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,4 +21,20 @@ protected override void OnDispose(bool calledExplicitly)
2121
=> Interlocked.Exchange(ref _action, null).Invoke();
2222

2323
}
24+
25+
public class DisposeHandler<T> : DisposeHandler
26+
{
27+
public DisposeHandler(T value, Action action) :base(action)
28+
{
29+
Value = value;
30+
}
31+
32+
public T Value { get; private set; }
33+
34+
protected override void OnDispose(bool calledExplicitly)
35+
{
36+
Value = default;
37+
base.OnDispose(calledExplicitly);
38+
}
39+
}
2440
}

Extensions.cs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
*/
55

66
using System;
7+
using System.Buffers;
78
using System.Collections.Generic;
89
using System.Diagnostics.Contracts;
910
using System.Linq;
@@ -52,5 +53,28 @@ public static void Dispose<T>(this ICollection<T> target, bool disposeContents =
5253
target.Clear();
5354
if (target is IDisposable t) t.Dispose();
5455
}
56+
57+
const int MaxPoolArraySize = 1024 * 1024;
58+
static void Dummy() { }
59+
60+
/// <summary>
61+
/// Rents a buffer from the ArrayPool but returns a DisposeHandler with the buffer as it's value.
62+
/// Facilitiates containing the temporary use of a buffer within a using block.
63+
/// If the mimimumLength exceeds 1024*1024, an array will be created at that length for use.
64+
/// </summary>
65+
/// <typeparam name="T">The type of the array.</typeparam>
66+
/// <param name="pool">The pool to get the array from.</param>
67+
/// <param name="minimumLength">The minimum length of the array.</param>
68+
/// <param name="clearArrayOnReturn">If true, will clear the array when it is returned to the pool.</param>
69+
/// <returns>A DisposeHandler containing an array of type T[] that is at least minimumLength in length.</returns>
70+
public static DisposeHandler<T[]> RentDisposable<T>(this ArrayPool<T> pool, int minimumLength, bool clearArrayOnReturn = false)
71+
{
72+
// If the size is too large, facilitate getting an array but don't manage the pool.
73+
if (minimumLength > MaxPoolArraySize)
74+
return new DisposeHandler<T[]>(new T[minimumLength], Dummy);
75+
76+
var a = pool.Rent(minimumLength);
77+
return new DisposeHandler<T[]>(a, () => pool.Return(a, clearArrayOnReturn));
78+
}
5579
}
5680
}

Open.Disposable.csproj

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,10 @@
1717
<PackageProjectUrl>https://github.com/electricessence/Open.Disposable/</PackageProjectUrl>
1818
<RepositoryUrl>https://github.com/electricessence/Open.Disposable/</RepositoryUrl>
1919
<RepositoryType>git</RepositoryType>
20-
<Version>2.0.0-preview3</Version>
20+
<Version>2.0.1</Version>
2121
<PackageReleaseNotes></PackageReleaseNotes>
22-
<AssemblyVersion>2.0.0.3</AssemblyVersion>
23-
<FileVersion>2.0.0.3</FileVersion>
22+
<AssemblyVersion>2.0.1.0</AssemblyVersion>
23+
<FileVersion>2.0.1.0</FileVersion>
2424
<PackageLicenseExpression>MIT</PackageLicenseExpression>
2525
</PropertyGroup>
2626

@@ -41,6 +41,7 @@
4141

4242
<ItemGroup Condition=" '$(TargetFramework)' == 'netstandard2.0' ">
4343
<PackageReference Include="System.Threading.Tasks.Extensions" Version="4.5.2" />
44+
<PackageReference Include="System.Memory" Version="4.5.3" />
4445
</ItemGroup>
4546

4647
<ItemGroup Condition=" '$(TargetFramework)' == 'netstandard2.1' ">

README.md

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,16 +24,24 @@ Aggressively attempting to help out the garbage collector can be serious anti-pa
2424

2525
## Classes
2626

27-
### DisposableBase
27+
### `DisposableBase`
2828

2929
Simply implement `void OnDispose(bool calledExplicitly)` in order to manage disposal.
3030

3131
If `calledExplicitly` is `true`, then the `.Dispose()` method was called by the code. If `false`, the class was finalized by the GC.
3232

33-
### AsyncDisposableBase
33+
> Note: `DisposableBase` exposes a `BeforeDispose` event which will be triggered once just before disposing commences. This allows for others to react to this disposal event. The `DisposableBase` is still considered 'live' until after the `BeforeDispose` event cycle has completed.
34+
35+
### `AsyncDisposableBase`
36+
37+
Inherits from `DisposableBase`.
3438

3539
Simply implement `ValueTask OnDisposeAsync(AsyncDisposeMode mode)` in order to manage disposal.
3640

3741
Dispose accordingly based upon the `AsyncDisposeMode`.
3842

3943
It is also possible to override `void OnDispose(bool calledExplicitly)` to manage synchronous disposal separate from asynchronous disposal, but should it must be understood that overriding without calling `base.OnDispose(calledExplicitly)` will mean that `OnDisposeAsync(AsyncDisposeMode mode)` will not automatically be called. Essentially meaning if you override, you should prepare for one or the other, but not both.
44+
45+
### `DisposeHandler` & `AsyncDisposeHandler`
46+
47+
A simple set of classes for triggering an action (once) when disposed. Can also contain a value (T) which is cleared on dispose.

0 commit comments

Comments
 (0)