@@ -26,20 +26,24 @@ public class AsyncSingleton<T> : IAsyncSingleton<T>
2626 private readonly Func < T > ? _syncFactory ;
2727 private readonly Func < CancellationToken , T > ? _syncFactoryToken ;
2828
29- public AsyncSingleton ( Func < ValueTask < T > > factory )
30- => _asyncFactory = factory ?? throw new ArgumentNullException ( nameof ( factory ) ) ;
29+ private readonly object ? _state ;
30+ private readonly Func < object , CancellationToken , ValueTask < T > > ? _asyncFactoryTokenState ;
3131
32- public AsyncSingleton ( Func < CancellationToken , ValueTask < T > > factory )
33- => _asyncFactoryToken = factory ?? throw new ArgumentNullException ( nameof ( factory ) ) ;
32+ public AsyncSingleton ( Func < ValueTask < T > > factory ) => _asyncFactory = factory ?? throw new ArgumentNullException ( nameof ( factory ) ) ;
3433
35- public AsyncSingleton ( Func < T > factory )
36- => _syncFactory = factory ?? throw new ArgumentNullException ( nameof ( factory ) ) ;
34+ public AsyncSingleton ( Func < CancellationToken , ValueTask < T > > factory ) => _asyncFactoryToken = factory ?? throw new ArgumentNullException ( nameof ( factory ) ) ;
3735
38- public AsyncSingleton ( Func < CancellationToken , T > factory )
39- => _syncFactoryToken = factory ?? throw new ArgumentNullException ( nameof ( factory ) ) ;
36+ public AsyncSingleton ( object state , Func < object , CancellationToken , ValueTask < T > > factory )
37+ {
38+ _state = state ?? throw new ArgumentNullException ( nameof ( state ) ) ;
39+ _asyncFactoryTokenState = factory ?? throw new ArgumentNullException ( nameof ( factory ) ) ;
40+ }
41+
42+ public AsyncSingleton ( Func < T > factory ) => _syncFactory = factory ?? throw new ArgumentNullException ( nameof ( factory ) ) ;
43+
44+ public AsyncSingleton ( Func < CancellationToken , T > factory ) => _syncFactoryToken = factory ?? throw new ArgumentNullException ( nameof ( factory ) ) ;
4045
41- public ValueTask < T > Get ( CancellationToken cancellationToken = default )
42- => GetOrCreate ( cancellationToken ) ;
46+ public ValueTask < T > Get ( CancellationToken cancellationToken = default ) => GetOrCreate ( cancellationToken ) ;
4347
4448 public virtual ValueTask < T > GetOrCreate ( CancellationToken cancellationToken = default )
4549 {
@@ -51,24 +55,26 @@ public virtual ValueTask<T> GetOrCreate(CancellationToken cancellationToken = de
5155 return new ValueTask < T > ( ( T ) _instance ! ) ;
5256
5357 return Slow ( cancellationToken ) ;
58+ }
5459
55- async ValueTask < T > Slow ( CancellationToken ct )
60+ private async ValueTask < T > Slow ( CancellationToken ct )
61+ {
62+ using ( await _lock . Lock ( ct )
63+ . NoSync ( ) )
5664 {
57- using ( await _lock . Lock ( ct ) . NoSync ( ) )
58- {
59- if ( _disposed . Value )
60- throw new ObjectDisposedException ( typeof ( AsyncSingleton < T > ) . Name ) ;
65+ if ( _disposed . Value )
66+ throw new ObjectDisposedException ( typeof ( AsyncSingleton < T > ) . Name ) ;
6167
62- if ( _hasValue . Value )
63- return ( T ) _instance ! ;
68+ if ( _hasValue . Value )
69+ return ( T ) _instance ! ;
6470
65- T created = await Create ( ct ) . NoSync ( ) ;
71+ T created = await Create ( ct )
72+ . NoSync ( ) ;
6673
67- _instance = created ! ;
68- _hasValue . Value = true ;
74+ _instance = created ! ;
75+ _hasValue . Value = true ;
6976
70- return created ;
71- }
77+ return created ;
7278 }
7379 }
7480
@@ -99,6 +105,9 @@ public T GetSync(CancellationToken cancellationToken = default)
99105
100106 private ValueTask < T > Create ( CancellationToken ct )
101107 {
108+ if ( _asyncFactoryTokenState is not null )
109+ return _asyncFactoryTokenState ( _state ! , ct ) ;
110+
102111 if ( _asyncFactoryToken is not null )
103112 return _asyncFactoryToken ( ct ) ;
104113
@@ -116,17 +125,22 @@ private ValueTask<T> Create(CancellationToken ct)
116125
117126 private T CreateSync ( CancellationToken ct )
118127 {
128+ if ( _asyncFactoryTokenState is not null )
129+ return _asyncFactoryTokenState ( _state ! , ct ) . AwaitSync ( ) ;
130+
119131 if ( _syncFactoryToken is not null )
120132 return _syncFactoryToken ( ct ) ;
121133
122134 if ( _syncFactory is not null )
123135 return _syncFactory ( ) ;
124136
125137 if ( _asyncFactoryToken is not null )
126- return _asyncFactoryToken ( ct ) . AwaitSync ( ) ;
138+ return _asyncFactoryToken ( ct )
139+ . AwaitSync ( ) ;
127140
128141 if ( _asyncFactory is not null )
129- return _asyncFactory ( ) . AwaitSync ( ) ;
142+ return _asyncFactory ( )
143+ . AwaitSync ( ) ;
130144
131145 throw new InvalidOperationException ( "No initialization factory was configured." ) ;
132146 }
@@ -147,7 +161,8 @@ public void Dispose()
147161
148162 // Prefer async disposal if supported (even in sync Dispose).
149163 if ( local is IAsyncDisposable ad )
150- ad . DisposeAsync ( ) . AwaitSync ( ) ;
164+ ad . DisposeAsync ( )
165+ . AwaitSync ( ) ;
151166 else if ( local is IDisposable d )
152167 d . Dispose ( ) ;
153168
@@ -161,18 +176,20 @@ public async ValueTask DisposeAsync()
161176
162177 object ? local ;
163178
164- using ( await _lock . Lock ( ) . NoSync ( ) )
179+ using ( await _lock . Lock ( )
180+ . NoSync ( ) )
165181 {
166182 _hasValue . Value = false ;
167183 local = _instance ;
168184 _instance = null ;
169185 }
170186
171187 if ( local is IAsyncDisposable ad )
172- await ad . DisposeAsync ( ) . NoSync ( ) ;
188+ await ad . DisposeAsync ( )
189+ . NoSync ( ) ;
173190 else if ( local is IDisposable d )
174191 d . Dispose ( ) ;
175192
176193 GC . SuppressFinalize ( this ) ;
177194 }
178- }
195+ }
0 commit comments