Skip to content

Commit 5c08619

Browse files
committed
Optimize Session Canceling process
1 parent a83f8f6 commit 5c08619

File tree

7 files changed

+38
-68
lines changed

7 files changed

+38
-68
lines changed

src/Kryptor.Cli/KeyStoreAnalyze/CrackSession.cs

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,12 @@ public class CrackSession : Session, ISessionHost
1414
public bool Found { get; private set; }
1515
public bool Verbose => false;
1616

17-
public CrackSession(int maxRunningSessions)
17+
CancellationTokenSource CancellationTokenSource;
18+
19+
public CrackSession(int maxRunningSessions, CancellationTokenSource cancellationTokenSource)
1820
{
21+
CancellationTokenSource = cancellationTokenSource;
22+
1923
Progress = -1;
2024

2125
container = new SessionContainer(this, maxRunningSessions);
@@ -39,7 +43,9 @@ protected override async Task<bool> RunAsync(ISessionHost sessionHost, Cancellat
3943
NewSession(session, false, true);
4044
}
4145

42-
await container.WaitAll(cancellationToken);
46+
await container.WaitAll();
47+
48+
cancellationToken.ThrowIfCancellationRequested();
4349

4450
return true;
4551
}
@@ -49,10 +55,7 @@ private void StopTimer()
4955
CalculationTimer.Stop();
5056
Found = true;
5157

52-
foreach (CancellationTokenSource token in container.TokenSources)
53-
{
54-
token.Cancel();
55-
}
58+
CancellationTokenSource.Cancel();
5659
}
5760

5861
public void Start(ClientContext context) => throw new System.NotImplementedException();
@@ -64,5 +67,7 @@ private void StopTimer()
6467
public void MonitorTask(Task task) => throw new System.NotImplementedException();
6568

6669
public Task<TResponse> OnSessionRequest<TResponse>(ISession session, SessionRequest<TResponse> request, CancellationToken cancellationToken) => throw new System.NotImplementedException();
70+
71+
public CancellationToken GetCancellationToken() => CancellationTokenSource.Token;
6772
}
6873
}

src/Kryptor.Cli/KeyStoreAnalyze/SessionHost.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ public override void Start(ClientContext context)
2222
KeyStoreLoadSession ksLoadSession = CreateKeyStoreLoadSession(ks);
2323
NewSession(ksLoadSession);
2424

25-
CrackSession calcSession = new CrackSession(maxRunningSessions);
25+
CrackSession calcSession = new CrackSession(maxRunningSessions, MasterToken);
2626
ksLoadSession.ContinueWith(calcSession);
2727
NewSession(calcSession);
2828

src/Kryptor.Client/ISessionHost.cs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,14 @@ public interface ISessionHost
2626
/// </param>
2727
void End(bool cancelled);
2828

29+
/// <summary>
30+
/// Gets the cancellation token of the session host.
31+
/// </summary>
32+
/// <returns>
33+
/// The global cancellation token of this session host.
34+
/// </returns>
35+
CancellationToken GetCancellationToken();
36+
2937
/// <summary>
3038
/// Starts a new session in this session host.
3139
/// </summary>

src/Kryptor.Client/SessionContainer.cs

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -30,19 +30,6 @@ public ISession[] Sessions
3030
/// </summary>
3131
public Task[] Tasks => SessionPool.Values.Select(x => x.Task).Concat(TaskPool).Where(x => x != null).ToArray();
3232

33-
/// <summary>
34-
/// Gets an array of all cancellation tokens.
35-
/// </summary>
36-
public CancellationTokenSource[] TokenSources
37-
{
38-
get
39-
{
40-
tokenSources ??= SessionPool.Values.Select(x => x.TokenSource).ToArray();
41-
42-
return tokenSources;
43-
}
44-
}
45-
4633
/// <summary>
4734
/// Gets all session holders.
4835
/// </summary>

src/Kryptor.Client/SessionHolder.cs

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,6 @@ public class SessionHolder
2020
/// </summary>
2121
public Task Task { get; private set; }
2222

23-
/// <summary>
24-
/// Gets the cancellation token source that controls the running session.
25-
/// </summary>
26-
public CancellationTokenSource TokenSource { get; set; }
27-
2823
internal bool AutoRemove { get; set; }
2924

3025
/// <summary>
@@ -33,18 +28,14 @@ public class SessionHolder
3328
/// <param name="session">
3429
/// The session instance.
3530
/// </param>
36-
/// <param name="tokenSource">
37-
/// The cancellation token source that controls the running task.
38-
/// </param>
39-
public SessionHolder(ISession session, CancellationTokenSource tokenSource)
31+
public SessionHolder(ISession session)
4032
{
4133
if (session.Status != SessionStatus.NotStarted)
4234
{
4335
throw new ArgumentException("The session is already started.");
4436
}
4537

4638
Session = session;
47-
TokenSource = tokenSource;
4839
}
4940

5041
/// <summary>
@@ -64,7 +55,7 @@ public Task StartTask(ISessionHost sessionHost, bool throwIfRunning = true)
6455
return throwIfRunning ? throw new InvalidOperationException("Session is already started.") : null;
6556
}
6657

67-
Task = Session.StartAsync(sessionHost, TokenSource.Token);
58+
Task = Session.StartAsync(sessionHost, sessionHost.GetCancellationToken());
6859
return Task;
6960
}
7061
}

src/Kryptor.Client/SessionHost.cs

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,18 @@ public abstract class SessionHost : ISessionHost
2323
/// <summary>
2424
/// Initializes all <see cref="SessionHost"/> instances.
2525
/// </summary>
26-
protected SessionHost()
26+
/// <param name="cancellationTokenSource">
27+
/// The cancellation token source to use in this session host.
28+
/// </param>
29+
protected SessionHost(CancellationTokenSource cancellationTokenSource = null)
2730
{
2831
Container = new SessionContainer(this, Environment.ProcessorCount - 1);
29-
MasterToken = new CancellationTokenSource();
32+
MasterToken = cancellationTokenSource ?? new CancellationTokenSource();
3033
}
3134

35+
/// <inheritdoc/>
36+
public CancellationToken GetCancellationToken() => MasterToken.Token;
37+
3238
/// <inheritdoc/>
3339
public abstract void Start(ClientContext context);
3440

@@ -44,8 +50,6 @@ public virtual void End(bool canceled)
4450

4551
if (canceled)
4652
{
47-
Container.Cancel();
48-
4953
MasterToken.Cancel();
5054

5155
// Tell to the SessionManager to do whatever needed

src/Kryptor.Client/SessionManager.cs

Lines changed: 8 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -50,29 +50,16 @@ public SessionContainer(ISessionHost sessionHost, int maxRunningSessions)
5050
/// </summary>
5151
/// <remarks>
5252
/// This method also waits for sessions that are not started yet.
53-
/// If the <paramref name="cancellationToken"/> was cancelled, this method will cancel all existing tokens in this container and waits for all of them to end.
54-
/// This method intended to be used by sub-session models. in standard session host based model, the monitoring, cancelling and ending is managed by various parts.
53+
/// This method intended to be used by sub-session models. in standard session host based model, the monitoring, canceling and ending is managed by various parts.
5554
/// But in sub-session models, you could achieve all of these features in this method.
56-
/// Using this method in session host is not recommended at all because this method is not intended for that porpose.
55+
/// Using this method in session host is not recommended at all because this method is not intended for that purpose.
5756
/// </remarks>
58-
/// <param name="cancellationToken">
59-
/// The token to monitor for cancellation requests.
60-
/// </param>
61-
public async Task WaitAll(CancellationToken cancellationToken)
57+
public async Task WaitAll()
6258
{
6359
while (!Sessions.All(x => x.Status == SessionStatus.Ended))
6460
{
65-
if (cancellationToken.IsCancellationRequested && !_cancellationRequested)
66-
{
67-
Cancel();
68-
69-
_cancellationRequested = true;
70-
}
71-
7261
await AsyncCompat.Delay(5);
7362
}
74-
75-
cancellationToken.ThrowIfCancellationRequested();
7663
}
7764

7865
/// <summary>
@@ -83,21 +70,10 @@ public async Task WaitAll(CancellationToken cancellationToken)
8370
/// A Task must be registered by <see cref="AddMonitoringTask(Task)"/> that waits for not started sessions before calling this method.
8471
/// This method only intended to be used in <see cref="ISessionHost.End(bool)"/>.
8572
/// so using it in sub-session models is not recommended as it could be lead to unexpected session exit and losing control of sub-sessions.
86-
/// it's highly recommended to use <see cref="WaitAll(CancellationToken)"/> method in that situation.
73+
/// it's highly recommended to use <see cref="WaitAll()"/> method in that situation.
8774
/// </remarks>
8875
public void WaitForRunningTasks() => Task.WaitAll(Tasks);
8976

90-
/// <summary>
91-
/// Sends cancellation request to all cancellation tokens in this container.
92-
/// </summary>
93-
public void Cancel()
94-
{
95-
foreach (CancellationTokenSource token in TokenSources.Where(x => !x.IsCancellationRequested))
96-
{
97-
token.Cancel();
98-
}
99-
}
100-
10177
/// <summary>
10278
/// Sets the provided <paramref name="sessionGroup"/> as the SessionManager's cache system.
10379
/// </summary>
@@ -194,9 +170,7 @@ public static SessionHolder WrapSession(ISession session, bool autoRemove)
194170
throw new ArgumentException("The session is already started.");
195171
}
196172

197-
CancellationTokenSource tokenSource = new CancellationTokenSource();
198-
199-
SessionHolder sessionHolder = new SessionHolder(session, tokenSource)
173+
SessionHolder sessionHolder = new SessionHolder(session)
200174
{
201175
AutoRemove = autoRemove
202176
};
@@ -275,6 +249,7 @@ private void ProcessTasks()
275249
if (_sessionHost.Verbose)
276250
{
277251
Console.WriteLine($"Error starting session: {ex.Message}");
252+
break;
278253
}
279254
}
280255
}
@@ -285,11 +260,11 @@ private void ProcessTasks()
285260
}
286261
}
287262

288-
private static bool SafeIsReady(SessionHolder holder)
263+
private bool SafeIsReady(SessionHolder holder)
289264
{
290265
try
291266
{
292-
return holder.Session.IsReady(holder.TokenSource.Token);
267+
return holder.Session.IsReady(_sessionHost.GetCancellationToken());
293268
}
294269
catch
295270
{

0 commit comments

Comments
 (0)