Skip to content

Commit 6c76509

Browse files
committed
ExplicitCancellation (and some small refactoring).
1 parent 3ce66f8 commit 6c76509

File tree

4 files changed

+174
-157
lines changed

4 files changed

+174
-157
lines changed

Provider/src/FirebirdSql.Data.FirebirdClient/Common/AsyncWrappingCommonArgs.cs

Lines changed: 37 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -24,153 +24,149 @@
2424
namespace FirebirdSql.Data.Common
2525
{
2626
[StructLayout(LayoutKind.Auto)]
27-
internal struct AsyncWrappingCommonArgs
27+
internal readonly struct AsyncWrappingCommonArgs
2828
{
2929
public static readonly AsyncWrappingCommonArgs Sync = new AsyncWrappingCommonArgs(false);
3030

31-
readonly bool _isAsync;
32-
readonly CancellationToken _cancellationTokenRaw;
33-
int _explicitCancel;
34-
public readonly bool IsAsync => _isAsync;
35-
public readonly CancellationToken CancellationToken => _explicitCancel > 0 ? CancellationToken.None : _cancellationTokenRaw;
31+
public readonly bool IsAsync { get; }
32+
public readonly CancellationToken CancellationToken { get; }
3633

3734
public AsyncWrappingCommonArgs(bool isAsync, CancellationToken cancellationToken = default)
3835
{
39-
_isAsync = isAsync;
40-
_cancellationTokenRaw = cancellationToken;
41-
_explicitCancel = 0;
36+
IsAsync = isAsync;
37+
CancellationToken = cancellationToken;
4238
}
4339

4440
public readonly Task<TResult> AsyncSyncCall<TResult>(Func<CancellationToken, Task<TResult>> asyncCall, Func<TResult> syncCall)
4541
{
46-
return _isAsync ? asyncCall(CancellationToken) : Task.FromResult(syncCall());
42+
return IsAsync ? asyncCall(CancellationToken) : Task.FromResult(syncCall());
4743
}
4844
public readonly Task<TResult> AsyncSyncCallNoCancellation<TResult>(Func<Task<TResult>> asyncCall, Func<TResult> syncCall)
4945
{
50-
return _isAsync ? asyncCall() : Task.FromResult(syncCall());
46+
return IsAsync ? asyncCall() : Task.FromResult(syncCall());
5147
}
5248
public readonly Task<TResult> AsyncSyncCall<T1, TResult>(Func<T1, CancellationToken, Task<TResult>> asyncCall, Func<T1, TResult> syncCall, T1 arg1)
5349
{
54-
return _isAsync ? asyncCall(arg1, CancellationToken) : Task.FromResult(syncCall(arg1));
50+
return IsAsync ? asyncCall(arg1, CancellationToken) : Task.FromResult(syncCall(arg1));
5551
}
5652
public readonly Task<TResult> AsyncSyncCallNoCancellation<T1, TResult>(Func<T1, Task<TResult>> asyncCall, Func<T1, TResult> syncCall, T1 arg1)
5753
{
58-
return _isAsync ? asyncCall(arg1) : Task.FromResult(syncCall(arg1));
54+
return IsAsync ? asyncCall(arg1) : Task.FromResult(syncCall(arg1));
5955
}
6056
public readonly Task<TResult> AsyncSyncCall<T1, T2, TResult>(Func<T1, T2, CancellationToken, Task<TResult>> asyncCall, Func<T1, T2, TResult> syncCall, T1 arg1, T2 arg2)
6157
{
62-
return _isAsync ? asyncCall(arg1, arg2, CancellationToken) : Task.FromResult(syncCall(arg1, arg2));
58+
return IsAsync ? asyncCall(arg1, arg2, CancellationToken) : Task.FromResult(syncCall(arg1, arg2));
6359
}
6460
public readonly Task<TResult> AsyncSyncCallNoCancellation<T1, T2, TResult>(Func<T1, T2, Task<TResult>> asyncCall, Func<T1, T2, TResult> syncCall, T1 arg1, T2 arg2)
6561
{
66-
return _isAsync ? asyncCall(arg1, arg2) : Task.FromResult(syncCall(arg1, arg2));
62+
return IsAsync ? asyncCall(arg1, arg2) : Task.FromResult(syncCall(arg1, arg2));
6763
}
6864
public readonly Task<TResult> AsyncSyncCall<T1, T2, T3, TResult>(Func<T1, T2, T3, CancellationToken, Task<TResult>> asyncCall, Func<T1, T2, T3, TResult> syncCall, T1 arg1, T2 arg2, T3 arg3)
6965
{
70-
return _isAsync ? asyncCall(arg1, arg2, arg3, CancellationToken) : Task.FromResult(syncCall(arg1, arg2, arg3));
66+
return IsAsync ? asyncCall(arg1, arg2, arg3, CancellationToken) : Task.FromResult(syncCall(arg1, arg2, arg3));
7167
}
7268
public readonly Task<TResult> AsyncSyncCallNoCancellation<T1, T2, T3, TResult>(Func<T1, T2, T3, Task<TResult>> asyncCall, Func<T1, T2, T3, TResult> syncCall, T1 arg1, T2 arg2, T3 arg3)
7369
{
74-
return _isAsync ? asyncCall(arg1, arg2, arg3) : Task.FromResult(syncCall(arg1, arg2, arg3));
70+
return IsAsync ? asyncCall(arg1, arg2, arg3) : Task.FromResult(syncCall(arg1, arg2, arg3));
7571
}
7672

7773
public readonly ValueTask<TResult> AsyncSyncCall<TResult>(Func<CancellationToken, ValueTask<TResult>> asyncCall, Func<TResult> syncCall)
7874
{
79-
return _isAsync ? asyncCall(CancellationToken) : ValueTask2.FromResult(syncCall());
75+
return IsAsync ? asyncCall(CancellationToken) : ValueTask2.FromResult(syncCall());
8076
}
8177
public readonly ValueTask<TResult> AsyncSyncCallNoCancellation<TResult>(Func<ValueTask<TResult>> asyncCall, Func<TResult> syncCall)
8278
{
83-
return _isAsync ? asyncCall() : ValueTask2.FromResult(syncCall());
79+
return IsAsync ? asyncCall() : ValueTask2.FromResult(syncCall());
8480
}
8581
public readonly ValueTask<TResult> AsyncSyncCall<T1, TResult>(Func<T1, CancellationToken, ValueTask<TResult>> asyncCall, Func<T1, TResult> syncCall, T1 arg1)
8682
{
87-
return _isAsync ? asyncCall(arg1, CancellationToken) : ValueTask2.FromResult(syncCall(arg1));
83+
return IsAsync ? asyncCall(arg1, CancellationToken) : ValueTask2.FromResult(syncCall(arg1));
8884
}
8985
public readonly ValueTask<TResult> AsyncSyncCallNoCancellation<T1, TResult>(Func<T1, ValueTask<TResult>> asyncCall, Func<T1, TResult> syncCall, T1 arg1)
9086
{
91-
return _isAsync ? asyncCall(arg1) : ValueTask2.FromResult(syncCall(arg1));
87+
return IsAsync ? asyncCall(arg1) : ValueTask2.FromResult(syncCall(arg1));
9288
}
9389
public readonly ValueTask<TResult> AsyncSyncCall<T1, T2, TResult>(Func<T1, T2, CancellationToken, ValueTask<TResult>> asyncCall, Func<T1, T2, TResult> syncCall, T1 arg1, T2 arg2)
9490
{
95-
return _isAsync ? asyncCall(arg1, arg2, CancellationToken) : ValueTask2.FromResult(syncCall(arg1, arg2));
91+
return IsAsync ? asyncCall(arg1, arg2, CancellationToken) : ValueTask2.FromResult(syncCall(arg1, arg2));
9692
}
9793
public readonly ValueTask<TResult> AsyncSyncCallNoCancellation<T1, T2, TResult>(Func<T1, T2, ValueTask<TResult>> asyncCall, Func<T1, T2, TResult> syncCall, T1 arg1, T2 arg2)
9894
{
99-
return _isAsync ? asyncCall(arg1, arg2) : ValueTask2.FromResult(syncCall(arg1, arg2));
95+
return IsAsync ? asyncCall(arg1, arg2) : ValueTask2.FromResult(syncCall(arg1, arg2));
10096
}
10197
public readonly ValueTask<TResult> AsyncSyncCall<T1, T2, T3, TResult>(Func<T1, T2, T3, CancellationToken, ValueTask<TResult>> asyncCall, Func<T1, T2, T3, TResult> syncCall, T1 arg1, T2 arg2, T3 arg3)
10298
{
103-
return _isAsync ? asyncCall(arg1, arg2, arg3, CancellationToken) : ValueTask2.FromResult(syncCall(arg1, arg2, arg3));
99+
return IsAsync ? asyncCall(arg1, arg2, arg3, CancellationToken) : ValueTask2.FromResult(syncCall(arg1, arg2, arg3));
104100
}
105101
public readonly ValueTask<TResult> AsyncSyncCallNoCancellation<T1, T2, T3, TResult>(Func<T1, T2, T3, ValueTask<TResult>> asyncCall, Func<T1, T2, T3, TResult> syncCall, T1 arg1, T2 arg2, T3 arg3)
106102
{
107-
return _isAsync ? asyncCall(arg1, arg2, arg3) : ValueTask2.FromResult(syncCall(arg1, arg2, arg3));
103+
return IsAsync ? asyncCall(arg1, arg2, arg3) : ValueTask2.FromResult(syncCall(arg1, arg2, arg3));
108104
}
109105

110106
public readonly Task AsyncSyncCall(Func<CancellationToken, Task> asyncCall, Action syncCall)
111107
{
112-
return _isAsync ? asyncCall(CancellationToken) : SyncTaskCompleted(Task.CompletedTask, syncCall);
108+
return IsAsync ? asyncCall(CancellationToken) : SyncTaskCompleted(Task.CompletedTask, syncCall);
113109
}
114110
public readonly Task AsyncSyncCallNoCancellation(Func<Task> asyncCall, Action syncCall)
115111
{
116-
return _isAsync ? asyncCall() : SyncTaskCompleted(Task.CompletedTask, syncCall);
112+
return IsAsync ? asyncCall() : SyncTaskCompleted(Task.CompletedTask, syncCall);
117113
}
118114
public readonly Task AsyncSyncCall<T1>(Func<T1, CancellationToken, Task> asyncCall, Action<T1> syncCall, T1 arg1)
119115
{
120-
return _isAsync ? asyncCall(arg1, CancellationToken) : SyncTaskCompleted(Task.CompletedTask, syncCall, arg1);
116+
return IsAsync ? asyncCall(arg1, CancellationToken) : SyncTaskCompleted(Task.CompletedTask, syncCall, arg1);
121117
}
122118
public readonly Task AsyncSyncCallNoCancellation<T1>(Func<T1, Task> asyncCall, Action<T1> syncCall, T1 arg1)
123119
{
124-
return _isAsync ? asyncCall(arg1) : SyncTaskCompleted(Task.CompletedTask, syncCall, arg1);
120+
return IsAsync ? asyncCall(arg1) : SyncTaskCompleted(Task.CompletedTask, syncCall, arg1);
125121
}
126122
public readonly Task AsyncSyncCall<T1, T2>(Func<T1, T2, CancellationToken, Task> asyncCall, Action<T1, T2> syncCall, T1 arg1, T2 arg2)
127123
{
128-
return _isAsync ? asyncCall(arg1, arg2, CancellationToken) : SyncTaskCompleted(Task.CompletedTask, syncCall, arg1, arg2);
124+
return IsAsync ? asyncCall(arg1, arg2, CancellationToken) : SyncTaskCompleted(Task.CompletedTask, syncCall, arg1, arg2);
129125
}
130126
public readonly Task AsyncSyncCallNoCancellation<T1, T2>(Func<T1, T2, Task> asyncCall, Action<T1, T2> syncCall, T1 arg1, T2 arg2)
131127
{
132-
return _isAsync ? asyncCall(arg1, arg2) : SyncTaskCompleted(Task.CompletedTask, syncCall, arg1, arg2);
128+
return IsAsync ? asyncCall(arg1, arg2) : SyncTaskCompleted(Task.CompletedTask, syncCall, arg1, arg2);
133129
}
134130
public readonly Task AsyncSyncCall<T1, T2, T3>(Func<T1, T2, T3, CancellationToken, Task> asyncCall, Action<T1, T2, T3> syncCall, T1 arg1, T2 arg2, T3 arg3)
135131
{
136-
return _isAsync ? asyncCall(arg1, arg2, arg3, CancellationToken) : SyncTaskCompleted(Task.CompletedTask, syncCall, arg1, arg2, arg3);
132+
return IsAsync ? asyncCall(arg1, arg2, arg3, CancellationToken) : SyncTaskCompleted(Task.CompletedTask, syncCall, arg1, arg2, arg3);
137133
}
138134
public readonly Task AsyncSyncCallNoCancellation<T1, T2, T3>(Func<T1, T2, T3, Task> asyncCall, Action<T1, T2, T3> syncCall, T1 arg1, T2 arg2, T3 arg3)
139135
{
140-
return _isAsync ? asyncCall(arg1, arg2, arg3) : SyncTaskCompleted(Task.CompletedTask, syncCall, arg1, arg2, arg3);
136+
return IsAsync ? asyncCall(arg1, arg2, arg3) : SyncTaskCompleted(Task.CompletedTask, syncCall, arg1, arg2, arg3);
141137
}
142138

143139
public readonly ValueTask AsyncSyncCall(Func<CancellationToken, ValueTask> asyncCall, Action syncCall)
144140
{
145-
return _isAsync ? asyncCall(CancellationToken) : SyncTaskCompleted(ValueTask2.CompletedTask, syncCall);
141+
return IsAsync ? asyncCall(CancellationToken) : SyncTaskCompleted(ValueTask2.CompletedTask, syncCall);
146142
}
147143
public readonly ValueTask AsyncSyncCallNoCancellation(Func<ValueTask> asyncCall, Action syncCall)
148144
{
149-
return _isAsync ? asyncCall() : SyncTaskCompleted(ValueTask2.CompletedTask, syncCall);
145+
return IsAsync ? asyncCall() : SyncTaskCompleted(ValueTask2.CompletedTask, syncCall);
150146
}
151147
public readonly ValueTask AsyncSyncCall<T1>(Func<T1, CancellationToken, ValueTask> asyncCall, Action<T1> syncCall, T1 arg1)
152148
{
153-
return _isAsync ? asyncCall(arg1, CancellationToken) : SyncTaskCompleted(ValueTask2.CompletedTask, syncCall, arg1);
149+
return IsAsync ? asyncCall(arg1, CancellationToken) : SyncTaskCompleted(ValueTask2.CompletedTask, syncCall, arg1);
154150
}
155151
public readonly ValueTask AsyncSyncCallNoCancellation<T1>(Func<T1, ValueTask> asyncCall, Action<T1> syncCall, T1 arg1)
156152
{
157-
return _isAsync ? asyncCall(arg1) : SyncTaskCompleted(ValueTask2.CompletedTask, syncCall, arg1);
153+
return IsAsync ? asyncCall(arg1) : SyncTaskCompleted(ValueTask2.CompletedTask, syncCall, arg1);
158154
}
159155
public readonly ValueTask AsyncSyncCall<T1, T2>(Func<T1, T2, CancellationToken, ValueTask> asyncCall, Action<T1, T2> syncCall, T1 arg1, T2 arg2)
160156
{
161-
return _isAsync ? asyncCall(arg1, arg2, CancellationToken) : SyncTaskCompleted(ValueTask2.CompletedTask, syncCall, arg1, arg2);
157+
return IsAsync ? asyncCall(arg1, arg2, CancellationToken) : SyncTaskCompleted(ValueTask2.CompletedTask, syncCall, arg1, arg2);
162158
}
163159
public readonly ValueTask AsyncSyncCallNoCancellation<T1, T2>(Func<T1, T2, ValueTask> asyncCall, Action<T1, T2> syncCall, T1 arg1, T2 arg2)
164160
{
165-
return _isAsync ? asyncCall(arg1, arg2) : SyncTaskCompleted(ValueTask2.CompletedTask, syncCall, arg1, arg2);
161+
return IsAsync ? asyncCall(arg1, arg2) : SyncTaskCompleted(ValueTask2.CompletedTask, syncCall, arg1, arg2);
166162
}
167163
public readonly ValueTask AsyncSyncCall<T1, T2, T3>(Func<T1, T2, T3, CancellationToken, ValueTask> asyncCall, Action<T1, T2, T3> syncCall, T1 arg1, T2 arg2, T3 arg3)
168164
{
169-
return _isAsync ? asyncCall(arg1, arg2, arg3, CancellationToken) : SyncTaskCompleted(ValueTask2.CompletedTask, syncCall, arg1, arg2, arg3);
165+
return IsAsync ? asyncCall(arg1, arg2, arg3, CancellationToken) : SyncTaskCompleted(ValueTask2.CompletedTask, syncCall, arg1, arg2, arg3);
170166
}
171167
public readonly ValueTask AsyncSyncCallNoCancellation<T1, T2, T3>(Func<T1, T2, T3, ValueTask> asyncCall, Action<T1, T2, T3> syncCall, T1 arg1, T2 arg2, T3 arg3)
172168
{
173-
return _isAsync ? asyncCall(arg1, arg2, arg3) : SyncTaskCompleted(ValueTask2.CompletedTask, syncCall, arg1, arg2, arg3);
169+
return IsAsync ? asyncCall(arg1, arg2, arg3) : SyncTaskCompleted(ValueTask2.CompletedTask, syncCall, arg1, arg2, arg3);
174170
}
175171

176172
[MethodImpl(MethodImplOptions.AggressiveInlining)]
@@ -197,41 +193,5 @@ static TTask SyncTaskCompleted<TTask, T1, T2, T3>(TTask completed, Action<T1, T2
197193
sync(arg1, arg2, arg3);
198194
return completed;
199195
}
200-
201-
public IDisposable EnterExplicitCancel(Action explicitCancel)
202-
{
203-
if (_cancellationTokenRaw.IsCancellationRequested)
204-
{
205-
explicitCancel();
206-
throw new OperationCanceledException(_cancellationTokenRaw);
207-
}
208-
_explicitCancel += 1;
209-
var ctr = _cancellationTokenRaw.Register(explicitCancel);
210-
return new ExitHolder(this, ctr);
211-
}
212-
213-
void ExitExplicitCancel(CancellationTokenRegistration cancellationTokenRegistration)
214-
{
215-
cancellationTokenRegistration.Dispose();
216-
_explicitCancel -= 1;
217-
}
218-
219-
[StructLayout(LayoutKind.Auto)]
220-
readonly struct ExitHolder : IDisposable
221-
{
222-
readonly AsyncWrappingCommonArgs _async;
223-
readonly CancellationTokenRegistration _cancellationTokenRegistration;
224-
225-
public ExitHolder(AsyncWrappingCommonArgs async, CancellationTokenRegistration cancellationTokenRegistration)
226-
{
227-
_async = async;
228-
_cancellationTokenRegistration = cancellationTokenRegistration;
229-
}
230-
231-
public void Dispose()
232-
{
233-
_async.ExitExplicitCancel(_cancellationTokenRegistration);
234-
}
235-
}
236196
}
237197
}
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
/*
2+
* The contents of this file are subject to the Initial
3+
* Developer's Public License Version 1.0 (the "License");
4+
* you may not use this file except in compliance with the
5+
* License. You may obtain a copy of the License at
6+
* https://github.com/FirebirdSQL/NETProvider/blob/master/license.txt.
7+
*
8+
* Software distributed under the License is distributed on
9+
* an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either
10+
* express or implied. See the License for the specific
11+
* language governing rights and limitations under the License.
12+
*
13+
* All Rights Reserved.
14+
*/
15+
16+
//$Authors = Jiri Cincura (jiri@cincura.net)
17+
18+
using System;
19+
using System.Runtime.CompilerServices;
20+
using System.Runtime.InteropServices;
21+
using System.Threading;
22+
23+
namespace FirebirdSql.Data.Common
24+
{
25+
internal static class ExplicitCancellation
26+
{
27+
public static ExplicitCancel Enter(CancellationToken cancellationToken, AsyncWrappingCommonArgs async, Action explicitCancel)
28+
{
29+
if (cancellationToken.IsCancellationRequested)
30+
{
31+
explicitCancel();
32+
throw new OperationCanceledException(cancellationToken);
33+
}
34+
var ctr = cancellationToken.Register(explicitCancel);
35+
return new ExplicitCancel(ctr, async);
36+
}
37+
38+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
39+
static void ExitExplicitCancel(CancellationTokenRegistration cancellationTokenRegistration)
40+
{
41+
cancellationTokenRegistration.Dispose();
42+
}
43+
44+
[StructLayout(LayoutKind.Auto)]
45+
internal readonly struct ExplicitCancel : IDisposable
46+
{
47+
readonly CancellationTokenRegistration _cancellationTokenRegistration;
48+
49+
public ExplicitCancel(CancellationTokenRegistration cancellationTokenRegistration, AsyncWrappingCommonArgs async)
50+
{
51+
_cancellationTokenRegistration = cancellationTokenRegistration;
52+
Async = new AsyncWrappingCommonArgs(async.IsAsync, CancellationToken.None);
53+
}
54+
55+
public void Dispose()
56+
{
57+
ExitExplicitCancel(_cancellationTokenRegistration);
58+
}
59+
60+
public readonly AsyncWrappingCommonArgs Async { get; }
61+
}
62+
}
63+
}

0 commit comments

Comments
 (0)