Skip to content

Commit 65d3465

Browse files
committed
Removes object[] allocation, generic typing instead
Improves various scenarios No longer AsyncSingleton... AsyncInitializer should be used instead
1 parent 1e6ba63 commit 65d3465

File tree

10 files changed

+319
-867
lines changed

10 files changed

+319
-867
lines changed

src/Abstract/IAsyncSingleton.cs

Lines changed: 0 additions & 74 deletions
This file was deleted.
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
using System;
2+
using System.Threading;
3+
using System.Threading.Tasks;
4+
5+
namespace Soenneker.Utils.AsyncSingleton.Abstract;
6+
7+
/// <summary>
8+
/// Represents an async-safe, single-initialization singleton that accepts one argument.
9+
/// The first successful initialization wins; subsequent calls reuse the instance.
10+
/// </summary>
11+
/// <typeparam name="T">The singleton instance type.</typeparam>
12+
/// <typeparam name="T1">The argument type used for initialization.</typeparam>
13+
public interface IAsyncSingleton<T, in T1> : IDisposable, IAsyncDisposable
14+
{
15+
/// <summary>
16+
/// Gets the singleton instance asynchronously, creating it if necessary.
17+
/// The first call initializes the instance using the provided argument.
18+
/// </summary>
19+
ValueTask<T> Get(T1 arg, CancellationToken cancellationToken = default);
20+
21+
/// <summary>
22+
/// Gets the singleton instance synchronously, creating it if necessary.
23+
/// The first call initializes the instance using the provided argument.
24+
/// </summary>
25+
T GetSync(T1 arg, CancellationToken cancellationToken = default);
26+
}

src/Abstract/IAsyncSingleton{T}.cs

Lines changed: 7 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -1,78 +1,23 @@
11
using System;
2-
using System.Diagnostics.Contracts;
32
using System.Threading;
43
using System.Threading.Tasks;
54

65
namespace Soenneker.Utils.AsyncSingleton.Abstract;
76

87
/// <summary>
9-
/// An externally initializing singleton that uses double-check asynchronous locking, with optional async and sync disposal
8+
/// Represents an async-safe singleton that initializes an instance of <typeparamref name="T"/> at most once.
9+
/// The first successful initialization wins; subsequent calls return the cached instance.
1010
/// </summary>
11-
/// <remarks>Be sure to dispose of this gracefully if using a Disposable type</remarks>
11+
/// <typeparam name="T">The singleton instance type.</typeparam>
1212
public interface IAsyncSingleton<T> : IDisposable, IAsyncDisposable
1313
{
1414
/// <summary>
15-
/// Utilizes double-check async locking to guarantee there's only one instance of the object. It's lazy; it's initialized only when retrieving. <para/>
16-
/// This method should be called even if the initialization func was synchronous.
15+
/// Gets the singleton instance asynchronously, creating it if necessary.
1716
/// </summary>
18-
/// <remarks>The initialization func needs to be set before calling this, either in the ctor or via the other methods</remarks>
19-
/// <exception cref="ObjectDisposedException"></exception>
20-
/// <exception cref="NullReferenceException"></exception>
21-
[Pure]
22-
ValueTask<T> Get(object[] objects);
17+
ValueTask<T> Get(CancellationToken cancellationToken = default);
2318

2419
/// <summary>
25-
/// Utilizes double-check async locking to guarantee there's only one instance of the object. It's lazy; it's initialized only when retrieving. <para/>
26-
/// This method should be called even if the initialization func was synchronous.
20+
/// Gets the singleton instance synchronously, creating it if necessary.
2721
/// </summary>
28-
/// <remarks>The initialization func needs to be set before calling this, either in the ctor or via the other methods</remarks>
29-
/// <exception cref="ObjectDisposedException"></exception>
30-
/// <exception cref="NullReferenceException"></exception>
31-
[Pure]
32-
ValueTask<T> Get(CancellationToken cancellationToken, params object[] objects);
33-
34-
/// <summary>
35-
/// Get should be used instead of this if possible. This method can block the calling thread! It's lazy; it's initialized only when retrieving. <para/>
36-
/// This can still be used with an async initialization func, but it will block on the func.
37-
/// </summary>
38-
/// <remarks>The initialization func needs to be set before calling this, either in the ctor or via the other methods</remarks>
39-
/// <exception cref="ObjectDisposedException"></exception>
40-
/// <exception cref="NullReferenceException"></exception>
41-
[Pure]
42-
T GetSync(object[] objects);
43-
44-
/// <see cref="SetInitialization(Func{T})"/>
45-
void SetInitialization(Func<CancellationToken, object[], ValueTask<T>> func);
46-
47-
/// <see cref="SetInitialization(Func{T})"/>
48-
void SetInitialization(Func<object[], ValueTask<T>> func);
49-
50-
/// <see cref="SetInitialization(Func{T})"/>
51-
void SetInitialization(Func<object[], T> func);
52-
53-
/// <see cref="SetInitialization(Func{T})"/>
54-
void SetInitialization(Func<CancellationToken, object[], T> func);
55-
56-
/// <summary>
57-
/// Typically not used. <para/>
58-
/// Allows for setting the initialization code outside the constructor. <para/>
59-
/// Initializing an AsyncSingleton after it's already has been set is not allowed
60-
/// </summary>
61-
void SetInitialization(Func<T> func);
62-
63-
/// <see cref="SetInitialization(Func{T})"/>
64-
void SetInitialization(Func<ValueTask<T>> func);
65-
66-
/// <summary>
67-
/// If the instance is an IDisposable, Dispose will be called on the method (and DisposeAsync will not) <para/>
68-
/// If the instance is ONLY an IAsyncDisposable and this is called, it will block while disposing. You should try to avoid this. <para/>
69-
/// </summary>
70-
/// <remarks>Disposal is not necessary unless the object's type is IDisposable/IAsyncDisposable</remarks>
71-
new void Dispose();
72-
73-
/// <summary>
74-
/// This is the preferred method of disposal. This will asynchronously dispose of the instance if the object is an IAsyncDisposable <para/>
75-
/// </summary>
76-
/// <remarks>Disposal is not necessary unless the object's type is IDisposable/IAsyncDisposable</remarks>
77-
new ValueTask DisposeAsync();
22+
T GetSync(CancellationToken cancellationToken = default);
7823
}

0 commit comments

Comments
 (0)