Skip to content

Commit 85bf200

Browse files
author
Oren (electricessence)
committed
Updated packaging.
Enabled nullable ref checking.
1 parent 4cdb925 commit 85bf200

13 files changed

+276
-291
lines changed

AsyncProcess.cs

+32-22
Original file line numberDiff line numberDiff line change
@@ -14,29 +14,32 @@ public class AsyncProcess<T> : DisposableBase
1414
where T : new()
1515
{
1616

17-
public AsyncProcess(Action<T> closure, TaskScheduler scheduler = null)
17+
protected AsyncProcess(TaskScheduler? scheduler)
1818
{
19-
Closure = closure;
20-
2119
Scheduler = scheduler ?? TaskScheduler.Default;
22-
Count = 0;
2320
}
2421

25-
protected readonly ReaderWriterLockSlim SyncLock = new ReaderWriterLockSlim();
22+
public AsyncProcess(Action<T> closure, TaskScheduler? scheduler = null)
23+
: this(scheduler)
24+
{
25+
Closure = closure ?? throw new ArgumentNullException(nameof(closure));
26+
}
27+
28+
protected ReaderWriterLockSlim? SyncLock = new ReaderWriterLockSlim();
2629

27-
protected TaskScheduler Scheduler
30+
protected TaskScheduler? Scheduler
2831
{
2932
get;
3033
private set;
3134
}
3235

33-
protected Action<T> Closure
36+
protected Action<T>? Closure
3437
{
3538
get;
3639
private set;
3740
}
3841

39-
protected Task InternalTask
42+
protected Task? InternalTask
4043
{
4144
get;
4245
set;
@@ -48,7 +51,7 @@ public virtual DateTime LatestCompleted
4851
protected set;
4952
}
5053

51-
public Exception LastFault
54+
public Exception? LastFault
5255
{
5356
get;
5457
protected set;
@@ -65,20 +68,20 @@ public int Count
6568
//long _processCount = 0;
6669
protected virtual void Process(object progress)
6770
{
68-
if (progress == null)
71+
if (progress is null)
6972
throw new ArgumentNullException(nameof(progress));
7073
Contract.EndContractBlock();
7174

7275
var p = (T)progress;
7376
try
7477
{
7578
//Contract.Assert(Interlocked.Increment(ref _processCount) == 1);
76-
Closure(p);
77-
SyncLock.Write(() => LatestCompleted = DateTime.Now);
79+
Closure!(p);
80+
SyncLock!.Write(() => LatestCompleted = DateTime.Now);
7881
}
7982
catch (Exception ex)
8083
{
81-
SyncLock.Write(() => LastFault = ex);
84+
SyncLock!.Write(() => LastFault = ex);
8285
}
8386
//finally
8487
//{
@@ -88,12 +91,12 @@ protected virtual void Process(object progress)
8891

8992
protected virtual Task EnsureProcess(bool once, TimeSpan? timeAllowedBeforeRefresh = null)
9093
{
91-
Task task = null;
92-
SyncLock.ReadWriteConditionalOptimized(
94+
Task? task = null;
95+
SyncLock!.ReadWriteConditionalOptimized(
9396
write =>
9497
{
9598
task = InternalTask;
96-
return (task == null || !once && !task.IsActive()) // No action, or completed?
99+
return (task is null || !once && !task.IsActive()) // No action, or completed?
97100
&& (!timeAllowedBeforeRefresh.HasValue // Now?
98101
|| timeAllowedBeforeRefresh.Value < DateTime.Now - LatestCompleted); // Or later?
99102
}, () =>
@@ -107,7 +110,7 @@ protected virtual Task EnsureProcess(bool once, TimeSpan? timeAllowedBeforeRefre
107110
}
108111
);
109112

110-
return task;
113+
return task!;
111114
}
112115

113116
// ReSharper disable once MemberCanBeProtected.Global
@@ -128,7 +131,7 @@ public virtual T Progress
128131
get
129132
{
130133
var t = InternalTask;
131-
if (t == null)
134+
if (t is null)
132135
return new T();
133136

134137
var state = t.AsyncState;
@@ -141,7 +144,9 @@ public virtual T Progress
141144

142145
protected override void OnDispose()
143146
{
144-
SyncLock.Dispose();
147+
var syncLock = Interlocked.Exchange(ref SyncLock, null)!;
148+
syncLock.Write(() => { }); // get exclusivity first.
149+
syncLock.Dispose();
145150
Scheduler = null;
146151
InternalTask = null;
147152
Closure = null;
@@ -151,8 +156,13 @@ protected override void OnDispose()
151156

152157
public class AsyncProcess : AsyncProcess<Progress>
153158
{
159+
protected AsyncProcess(TaskScheduler? scheduler) : base(scheduler)
160+
{
161+
162+
}
163+
154164
// ReSharper disable once MemberCanBeProtected.Global
155-
public AsyncProcess(Action<Progress> closure, TaskScheduler scheduler = null)
165+
public AsyncProcess(Action<Progress> closure, TaskScheduler? scheduler = null)
156166
: base(closure, scheduler)
157167
{
158168
}
@@ -179,11 +189,11 @@ protected override void Process(object progress)
179189
try
180190
{
181191
//Contract.Assert(Interlocked.Increment(ref _processCount) == 1);
182-
Closure(p);
192+
Closure!(p);
183193
}
184194
catch (Exception ex)
185195
{
186-
SyncLock.Write(() => LatestCompleted = DateTime.Now);
196+
SyncLock!.Write(() => LatestCompleted = DateTime.Now);
187197
p.Failed(ex.ToString());
188198
}
189199
//finally

AsyncQuery.cs

+37-27
Original file line numberDiff line numberDiff line change
@@ -1,40 +1,44 @@
11
using System;
2+
using System.Diagnostics.CodeAnalysis;
23
using System.Threading.Tasks;
34

45
namespace Open.Threading.Tasks
56
{
67
public class AsyncQuery<TResult> : AsyncProcess
78
{
8-
TResult _latest;
9+
#if NETSTANDARD2_1
10+
[AllowNull]
11+
#endif
12+
TResult _latest = default!;
913

10-
protected new Func<Progress, TResult> Closure
14+
protected new Func<Progress, TResult>? Closure
1115
{
1216
get;
1317
private set;
1418
}
1519

16-
protected Task<TResult> InternalTaskValued
20+
protected Task<TResult>? InternalTaskValued
1721
{
1822
get;
1923
private set;
2024
}
2125

22-
public AsyncQuery(Func<Progress, TResult> query, TaskScheduler scheduler = null)
23-
: base(null, scheduler)
26+
public AsyncQuery(Func<Progress, TResult> query, TaskScheduler? scheduler = null)
27+
: base(scheduler)
2428
{
25-
Closure = query;
29+
Closure = query ?? throw new ArgumentNullException(nameof(query));
2630
}
2731

2832
protected Task<TResult> EnsureProcessValued(bool once, TimeSpan? timeAllowedBeforeRefresh = null)
2933
{
3034

31-
Task<TResult> task = null;
35+
Task<TResult>? task = null;
3236

33-
SyncLock.ReadWriteConditionalOptimized(
37+
SyncLock!.ReadWriteConditionalOptimized(
3438
write =>
3539
{
3640
task = InternalTaskValued;
37-
return (task == null || !once && !task.IsActive()) // No action, or completed?
41+
return (task is null || !once && !task.IsActive()) // No action, or completed?
3842
&& (!timeAllowedBeforeRefresh.HasValue // Now?
3943
|| timeAllowedBeforeRefresh.Value < DateTime.Now - LatestCompleted); // Or later?
4044
}, () =>
@@ -49,44 +53,45 @@ protected Task<TResult> EnsureProcessValued(bool once, TimeSpan? timeAllowedBefo
4953
);
5054

5155
// action could be null in some cases where timeAllowedBeforeRefresh condition is still met.
52-
return task;
56+
return task!;
5357
}
5458

5559
protected override Task EnsureProcess(bool once, TimeSpan? timeAllowedBeforeRefresh = null)
56-
{
57-
return EnsureProcessValued(once, timeAllowedBeforeRefresh);
58-
}
60+
=> EnsureProcessValued(once, timeAllowedBeforeRefresh);
5961

6062
//long _processCount = 0;
63+
#if NETSTANDARD2_1
64+
[return: MaybeNull]
65+
#endif
6166
protected new TResult Process(object progress)
6267
{
6368

6469
var p = (Progress)progress;
6570
try
6671
{
6772
//Contract.Assert(Interlocked.Increment(ref _processCount) == 1);
68-
var result = Closure(p);
73+
var result = Closure!(p);
6974
Latest = result;
7075
return result;
7176
}
7277
catch (Exception ex)
7378
{
74-
SyncLock.Write(() => LatestCompleted = DateTime.Now);
79+
SyncLock!.Write(() => LatestCompleted = DateTime.Now);
7580
p.Failed(ex.ToString());
7681
}
7782
//finally
7883
//{
7984
// //Interlocked.Decrement(ref _processCount);
8085
//}
81-
return default;
86+
return default!;
8287
}
8388

8489
public bool IsCurrentDataReady
8590
{
8691
get
8792
{
8893
var t = InternalTask;
89-
if (t == null)
94+
if (t is null)
9095
return false;
9196
return !t.IsActive();
9297
}
@@ -124,7 +129,7 @@ protected virtual TResult GetLatest()
124129

125130
public virtual void OverrideLatest(TResult value, DateTime? completed = null)
126131
{
127-
SyncLock.Write(() =>
132+
SyncLock!.Write(() =>
128133
{
129134
_latest = value;
130135
LatestCompleted = completed ?? DateTime.Now;
@@ -134,7 +139,7 @@ public virtual void OverrideLatest(TResult value, DateTime? completed = null)
134139

135140
public virtual void OverrideLatest(TResult value, Func<TResult, TResult, bool> useNewValueEvaluator, DateTime? completed = null)
136141
{
137-
SyncLock.ReadWriteConditionalOptimized(
142+
SyncLock!.ReadWriteConditionalOptimized(
138143
(write) => useNewValueEvaluator(_latest, value),
139144
() =>
140145
{
@@ -155,8 +160,8 @@ public TResult Latest
155160

156161
public bool WaitForRunningToComplete(TimeSpan? waitForCurrentTimeout = null)
157162
{
158-
var task = SyncLock.ReadValue(() => InternalTaskValued);
159-
if (task == null) return false;
163+
var task = SyncLock!.ReadValue(() => InternalTaskValued);
164+
if (task is null) return false;
160165
if (waitForCurrentTimeout.HasValue)
161166
task.Wait(waitForCurrentTimeout.Value);
162167
else
@@ -169,8 +174,8 @@ public TResult RunningValue
169174
{
170175
get
171176
{
172-
var task = SyncLock.ReadValue(() => InternalTaskValued);
173-
return task == null ? GetRunningValue() : task.Result;
177+
var task = SyncLock!.ReadValue(() => InternalTaskValued);
178+
return task is null ? GetRunningValue() : task.Result;
174179
}
175180
}
176181

@@ -186,17 +191,22 @@ public TResult ActiveRunningValueOrLatestPossible
186191
}
187192
}
188193

189-
public virtual bool TryGetLatest(out TResult latest, out DateTime completed)
194+
public virtual bool TryGetLatest(
195+
#if NETSTANDARD2_1
196+
[NotNullWhen(true)]
197+
#endif
198+
out TResult latest,
199+
out DateTime completed)
190200
{
191201
var result = default(TResult);
192202
var resultComplete = DateTime.MinValue;
193-
var isReady = SyncLock.ReadValue(() =>
203+
var isReady = SyncLock!.ReadValue(() =>
194204
{
195205
result = _latest;
196206
resultComplete = LatestCompleted;
197207
return IsLatestAvailable;
198208
});
199-
latest = result;
209+
latest = result!;
200210
completed = resultComplete;
201211
return isReady;
202212
}
@@ -255,7 +265,7 @@ public TResult GetLatestOrRunning(out DateTime completed)
255265
protected override void OnDispose()
256266
{
257267
base.OnDispose();
258-
_latest = default;
268+
_latest = default!;
259269
Closure = null;
260270
}
261271
}

0 commit comments

Comments
 (0)