Skip to content
This repository was archived by the owner on Feb 14, 2022. It is now read-only.

Commit 8543925

Browse files
authored
Merge pull request #124 from JacopoWolf/rel/3.1
Stable release 3.1.0
2 parents 5074147 + d9eee22 commit 8543925

36 files changed

Lines changed: 679 additions & 394 deletions

.github/dependabot.yml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
version: 2
77
updates:
88

9+
910
# prod
1011
- package-ecosystem: "nuget"
1112
directory: "/StackInjector"
@@ -26,10 +27,10 @@ updates:
2627
- "dependencies"
2728
- "testing"
2829

30+
2931
#todo: add TEST.WhiteBox
3032

3133

32-
3334
# ci
3435
- package-ecosystem: "github-actions"
3536
# Workflow files stored in the

.github/workflows/dotnetcore.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,12 @@ on:
1414

1515

1616
jobs:
17-
1817
test:
1918
runs-on: ${{ matrix.os }}
2019
env:
2120
DOTNET_NOLOGO: true
2221
strategy:
22+
fail-fast: false
2323
matrix:
2424
os: [ubuntu-latest, windows-latest]
2525
dotnet: ['3.1.x']

StackInjector/Attributes/ServedAttribute.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ public sealed class ServedAttribute : Attribute
1313
/// <summary>
1414
/// The target version.
1515
/// </summary>
16-
public double TargetVersion { get; set; } = 0.0;
16+
public double TargetVersion { get; set; }
1717

1818
/// <summary>
1919
/// <para>How the specified TargetVersion should be found.</para>
@@ -31,7 +31,7 @@ public ServedVersionTargetingMethod TargetingMethod
3131

3232

3333
private ServedVersionTargetingMethod _targeting;
34-
internal bool _targetingDefined = false;
34+
internal bool _targetingDefined;
3535

3636
}
3737

StackInjector/Attributes/ServiceAttribute.cs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,11 @@ public sealed class ServiceAttribute : Attribute
1717
/// <summary>
1818
/// The instantiation pattern for this service.
1919
/// </summary>
20-
public InstantiationPattern Pattern { get; set; } = InstantiationPattern.Singleton;
20+
public InstantiationPattern Pattern
21+
{
22+
get => this._pattern;
23+
set => this._pattern = value;
24+
}
2125

2226

2327
/// <summary>
@@ -33,8 +37,9 @@ public ServingMethods Serving
3337
}
3438
}
3539

40+
private InstantiationPattern _pattern = InstantiationPattern.Singleton;
3641
private ServingMethods _serving;
37-
internal bool _servingDefined = false;
42+
internal bool _servingDefined;
3843
}
3944

4045
}

StackInjector/Behaviours/IInstancesHolder.cs

Lines changed: 0 additions & 36 deletions
This file was deleted.

StackInjector/Behaviours/SingleInstanceHolder.cs

Lines changed: 0 additions & 69 deletions
This file was deleted.

StackInjector/Core/AsyncStackWrapperCore.cs

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@ namespace StackInjector.Core
88
internal abstract partial class AsyncStackWrapperCore<T> : StackWrapperCore, IAsyncStackWrapperCore<T>
99
{
1010

11+
public event Action<T> OnElaborated;
12+
13+
1114
// used to cancel everything
1215
protected internal readonly CancellationTokenSource cancelPendingTasksSource = new CancellationTokenSource();
1316

@@ -16,38 +19,41 @@ public CancellationToken PendingTasksCancellationToken
1619
=> this.cancelPendingTasksSource.Token;
1720

1821
// used to lock access to tasks
19-
protected internal readonly object listAccessLock = new object();
22+
private readonly object _listAccessLock = new object();
23+
24+
// used to endure Elaborated() and Elaborate() are called together
25+
private bool _exclusiveExecution;
26+
27+
public bool IsElaborating => this._exclusiveExecution;
2028

2129
// asyncronously waited for new events if TaskList is empty
22-
protected internal readonly SemaphoreSlim emptyListAwaiter = new SemaphoreSlim(0);
30+
private readonly SemaphoreSlim _emptyListAwaiter = new SemaphoreSlim(0);
2331

2432
// pending tasks
2533
protected internal LinkedList<Task<T>> tasks = new LinkedList<Task<T>>();
2634

2735

28-
internal AsyncStackWrapperCore ( InjectionCore core, Type toRegister ) : base(core, toRegister)
29-
{
30-
// register an event that in case the list is empty, release the empty event listener.
36+
// register an event that in case the list is empty, release the empty event listener.
37+
internal AsyncStackWrapperCore ( InjectionCore core, Type toRegister ) : base(core, toRegister) =>
3138
this.cancelPendingTasksSource.Token.Register(this.ReleaseListAwaiter);
32-
}
3339

3440

3541

3642
#region IDisposable Support
3743

38-
private bool disposedValue = false;
44+
private bool disposedValue;
3945

4046
public override void Dispose ()
4147
{
4248
if( !this.disposedValue )
4349
{
4450

4551
// managed resources
46-
this.cancelPendingTasksSource.Cancel();
52+
this.cancelPendingTasksSource.Cancel(); // cancel all pending tasks
4753
this.ReleaseListAwaiter(); // in case it's waiting on the empty list
4854

4955
this.cancelPendingTasksSource.Dispose();
50-
this.emptyListAwaiter.Dispose();
56+
this._emptyListAwaiter.Dispose();
5157

5258

5359
// big objects
@@ -61,7 +67,6 @@ public override void Dispose ()
6167
this.disposedValue = true;
6268
}
6369
}
64-
6570
#endregion
6671
}
6772

StackInjector/Core/AsyncStackWrapperCore.logic.cs

Lines changed: 42 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
using System.Collections.Generic;
1+
using System;
2+
using System.Collections.Generic;
23
using System.Linq;
34
using System.Threading.Tasks;
45
using StackInjector.Settings;
@@ -8,14 +9,12 @@ namespace StackInjector.Core
89
internal abstract partial class AsyncStackWrapperCore<T>
910
{
1011
// call the semaphore
11-
protected internal void ReleaseListAwaiter ()
12-
{
13-
this.emptyListAwaiter.Release();
14-
}
12+
protected internal void ReleaseListAwaiter () => this._emptyListAwaiter.Release();
13+
1514

16-
public void Submit ( Task<T> work )
15+
internal void Submit ( Task<T> work )
1716
{
18-
lock( this.listAccessLock )
17+
lock( this._listAccessLock )
1918
this.tasks.AddLast(work);
2019

2120
// if the list was empty just an item ago, signal it's not anymore.
@@ -24,22 +23,33 @@ public void Submit ( Task<T> work )
2423
this.ReleaseListAwaiter();
2524
}
2625

26+
2727
public bool AnyTaskLeft ()
2828
{
29-
lock( this.listAccessLock )
29+
lock( this._listAccessLock )
3030
return this.tasks.Any();
3131
}
3232

33+
public bool AnyTaskCompleted ()
34+
{
35+
lock( this._listAccessLock )
36+
return this.tasks.Any(t => t.IsCompleted);
37+
}
38+
3339
public async IAsyncEnumerable<T> Elaborated ()
3440
{
41+
this.EnsureExclusiveExecution(true);
42+
3543
while( !this.cancelPendingTasksSource.IsCancellationRequested )
3644
{
3745
// avoid deadlocks
3846
if( this.AnyTaskLeft() )
3947
{
4048
var completed = await Task.WhenAny(this.tasks).ConfigureAwait(false);
4149

42-
lock( this.listAccessLock )
50+
51+
52+
lock( this._listAccessLock )
4353
this.tasks.Remove(completed);
4454

4555
yield return completed.Result;
@@ -51,14 +61,25 @@ public async IAsyncEnumerable<T> Elaborated ()
5161
break;
5262
}
5363
}
64+
65+
lock( this._listAccessLock )
66+
this._exclusiveExecution = false;
67+
68+
}
69+
70+
public async Task Elaborate ()
71+
{
72+
await foreach( var res in this.Elaborated() )
73+
this.OnElaborated?.Invoke(res);
5474
}
5575

76+
5677
// true if outher loop is to break
5778
private async Task<bool> OnNoTasksLeft ()
5879
{
5980
// to not repeat code
6081
Task listAwaiter ()
61-
=> this.emptyListAwaiter.WaitAsync();
82+
=> this._emptyListAwaiter.WaitAsync();
6283

6384

6485
switch( this.Settings._asyncWaitingMethod )
@@ -86,10 +107,18 @@ Task listAwaiter ()
86107
}
87108
}
88109

110+
private void EnsureExclusiveExecution ( bool set = false )
111+
{
112+
lock( this._listAccessLock ) // reused lock
113+
{
114+
if( this._exclusiveExecution )
115+
throw new InvalidOperationException();
116+
117+
if( set )
118+
this._exclusiveExecution = set;
119+
}
120+
}
89121

90-
public bool AnyTaskCompleted ()
91-
=>
92-
this.tasks.Any(t => t.IsCompleted);
93122

94123

95124
}

StackInjector/Core/Cloning/ClonedCore.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ public IAsyncStackWrapper<TEntry, TIn, TOut> ToAsyncWrapper<TEntry, TIn, TOut> (
1919
StackDigest = digest
2020
};
2121

22-
this.clonedCore.EntryPoint = typeof(TEntry);
22+
this.clonedCore.EntryType = typeof(TEntry);
2323
this.clonedCore.ServeAll();
2424

2525
return wrapper;
@@ -29,7 +29,7 @@ public IStackWrapper<T> ToWrapper<T> ()
2929
{
3030
var wrapper = new StackWrapper<T>(this.clonedCore);
3131

32-
this.clonedCore.EntryPoint = typeof(T);
32+
this.clonedCore.EntryType = typeof(T);
3333
this.clonedCore.ServeAll();
3434

3535
return wrapper;

0 commit comments

Comments
 (0)