Skip to content

Commit 9b4233c

Browse files
Merge pull request #45 from ShawnLaMountain/Minor-Fixes
Added New Extentions
2 parents 25aee73 + e6268d9 commit 9b4233c

14 files changed

Lines changed: 183 additions & 54 deletions

‎README.md‎

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -44,8 +44,10 @@ A simple C# repository containing a few basic useful Thread-Safe Objects.
4444
- DataObject
4545
- Extentions
4646
- IBindableObjectExtention
47+
- IMethodThreadLocksExtentions
4748
- INotifyCollectionChangedExtension
4849
- INotifyPropertyChangedExtension
50+
- ISingleThreadLockExtentions
4951
- ObjectExtention
5052
- HelperClasses
5153
- ThreadHelper
@@ -64,8 +66,8 @@ A simple C# repository containing a few basic useful Thread-Safe Objects.
6466
- IHashSetThreadSafe
6567
- ILinkedListThreadSafe
6668
- IListThreadSafe
67-
- IMethodThreadLock
68-
- IMultipleThreadLockManager\<TKey, TValue>
69+
- IMethodThreadLocks
70+
- IMultipleThreadLocks\<TKey>
6971
- IObservableCollectionThreadSafe
7072
- IObservableCollectionThreadSafe\<T>
7173
- IObservableDataCollection
@@ -87,8 +89,8 @@ A simple C# repository containing a few basic useful Thread-Safe Objects.
8789
- Locks
8890
- GatedThreadLock
8991
- GateKeeper
90-
- MethodThreadLock
91-
- MultipleThreadLockManager
92+
- MethodThreadLocks
93+
- MultipleThreadLocks
9294
- SingleThreadLock
9395

9496
----
@@ -454,6 +456,17 @@ This can be overwritten durring creation or by setting Property `WaitOnNotifyCol
454456
Observable Objects Property `WaitOnNotifyPropertyChanged` has been renamed to Property `WaitOnNotifying`.
455457

456458
Observable Collections Property `WaitOnNotifyCollectionChanged` has been removed and now uses Property `WaitOnNotifying`.
459+
460+
461+
## Breaking changes from v3.1.1 to v3.1.2!
462+
463+
Lock `MethodThreadLock` has been renamed to `MethodThreadLocks`.
464+
465+
Interface `IMethodThreadLock` has been renamed to `IMethodThreadLocks`.
466+
467+
Lock `MultipleThreadLockManager` has been renamed to `MultipleThreadLocks`.
468+
469+
Interface `IMultipleThreadLockManager` has been renamed to `IMultipleThreadLocks`.
457470
----
458471

459472

src/ThunderDesign.Net-PCL.Threading.UnitTests/Locks/MethodThreadLockTests.cs renamed to src/ThunderDesign.Net-PCL.Threading.UnitTests/Locks/MethodThreadLocksTests.cs

Lines changed: 32 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -6,44 +6,44 @@
66

77
namespace ThunderDesign.Net_PCL.Threading.UnitTests.Locks
88
{
9-
public class MethodThreadLockTests
9+
public class MethodThreadLocksTests
1010
{
11-
private async Task MethodA(MethodThreadLock methodLock, int delayMs)
11+
private async Task MethodA(MethodThreadLocks methodLocks, int delayMs)
1212
{
13-
await methodLock.LockAsync();
13+
await methodLocks.LockAsync();
1414
try
1515
{
1616
await Task.Delay(delayMs);
1717
}
1818
finally
1919
{
20-
methodLock.Unlock();
20+
methodLocks.Unlock();
2121
}
2222
}
2323

24-
private async Task MethodB(MethodThreadLock methodLock, int delayMs)
24+
private async Task MethodB(MethodThreadLocks methodLocks, int delayMs)
2525
{
26-
await methodLock.LockAsync();
26+
await methodLocks.LockAsync();
2727
try
2828
{
2929
await Task.Delay(delayMs);
3030
}
3131
finally
3232
{
33-
methodLock.Unlock();
33+
methodLocks.Unlock();
3434
}
3535
}
3636

3737
[Fact]
3838
public async Task LockAsync_ShouldUseCallerMemberName_ToScopeLock()
3939
{
40-
using var methodLock = new MethodThreadLock();
40+
using var methodLocks = new MethodThreadLocks();
4141

42-
var firstCall = MethodA(methodLock, 200);
42+
var firstCall = MethodA(methodLocks, 200);
4343

4444
await Task.Delay(20); // allow first call to acquire lock
4545

46-
var secondCall = MethodA(methodLock, 20);
46+
var secondCall = MethodA(methodLocks, 20);
4747

4848
var completedEarly = await Task.WhenAny(secondCall, Task.Delay(50)) == secondCall;
4949
Assert.False(completedEarly);
@@ -54,10 +54,10 @@ public async Task LockAsync_ShouldUseCallerMemberName_ToScopeLock()
5454
[Fact]
5555
public async Task LockAsync_ShouldNotBlock_DifferentMethods()
5656
{
57-
using var methodLock = new MethodThreadLock();
57+
using var methodLocks = new MethodThreadLocks();
5858

59-
var callA = MethodA(methodLock, 200);
60-
var callB = MethodB(methodLock, 200);
59+
var callA = MethodA(methodLocks, 200);
60+
var callB = MethodB(methodLocks, 200);
6161

6262
var completed = await Task.WhenAny(Task.WhenAll(callA, callB), Task.Delay(500));
6363

@@ -67,44 +67,44 @@ public async Task LockAsync_ShouldNotBlock_DifferentMethods()
6767
[Fact]
6868
public async Task LockAsync_WithExplicitMethodName_ShouldScopeIndependently()
6969
{
70-
using var methodLock = new MethodThreadLock();
70+
using var methodLocks = new MethodThreadLocks();
7171

72-
await methodLock.LockAsync("CustomKey1");
72+
await methodLocks.LockAsync("CustomKey1");
7373

74-
var otherKeyTask = methodLock.LockAsync("CustomKey2");
74+
var otherKeyTask = methodLocks.LockAsync("CustomKey2");
7575
var completed = await Task.WhenAny(otherKeyTask, Task.Delay(500)) == otherKeyTask;
7676

7777
Assert.True(completed);
7878

79-
methodLock.Unlock("CustomKey1");
80-
methodLock.Unlock("CustomKey2");
79+
methodLocks.Unlock("CustomKey1");
80+
methodLocks.Unlock("CustomKey2");
8181
}
8282

8383
[Fact]
8484
public async Task LockAsync_ShouldThrowArgumentNullException_WhenMethodNameIsNullOrWhiteSpace()
8585
{
86-
using var methodLock = new MethodThreadLock();
86+
using var methodLocks = new MethodThreadLocks();
8787

88-
await Assert.ThrowsAsync<ArgumentNullException>(() => methodLock.LockAsync(" "));
88+
await Assert.ThrowsAsync<ArgumentNullException>(() => methodLocks.LockAsync(" "));
8989
}
9090

9191
[Fact]
9292
public void Unlock_ShouldThrowArgumentNullException_WhenMethodNameIsNullOrWhiteSpace()
9393
{
94-
using var methodLock = new MethodThreadLock();
94+
using var methodLocks = new MethodThreadLocks();
9595

96-
Assert.Throws<ArgumentNullException>(() => methodLock.Unlock(" "));
96+
Assert.Throws<ArgumentNullException>(() => methodLocks.Unlock(" "));
9797
}
9898

9999
[Fact]
100100
public async Task LockAsync_ShouldThrowOperationCanceledException_WhenCancelled()
101101
{
102-
using var methodLock = new MethodThreadLock();
102+
using var methodLocks = new MethodThreadLocks();
103103

104-
await methodLock.LockAsync(nameof(LockAsync_ShouldThrowOperationCanceledException_WhenCancelled));
104+
await methodLocks.LockAsync(nameof(LockAsync_ShouldThrowOperationCanceledException_WhenCancelled));
105105

106106
using var cts = new CancellationTokenSource();
107-
var waitingTask = methodLock.LockAsync(nameof(LockAsync_ShouldThrowOperationCanceledException_WhenCancelled), cts.Token);
107+
var waitingTask = methodLocks.LockAsync(nameof(LockAsync_ShouldThrowOperationCanceledException_WhenCancelled), cts.Token);
108108

109109
cts.Cancel();
110110

@@ -114,27 +114,27 @@ public async Task LockAsync_ShouldThrowOperationCanceledException_WhenCancelled(
114114
[Fact]
115115
public async Task LockAsync_ShouldThrowObjectDisposedException_WhenDisposedWhileWaiting()
116116
{
117-
var methodLock = new MethodThreadLock();
117+
var methodLocks = new MethodThreadLocks();
118118

119-
await methodLock.LockAsync("SharedMethod");
119+
await methodLocks.LockAsync("SharedMethod");
120120

121-
var waitingTask = methodLock.LockAsync("SharedMethod");
122-
methodLock.Dispose();
121+
var waitingTask = methodLocks.LockAsync("SharedMethod");
122+
methodLocks.Dispose();
123123

124124
await Assert.ThrowsAsync<ObjectDisposedException>(() => waitingTask);
125125
}
126126

127127
[Fact]
128128
public async Task LockAsync_ShouldOnlyAllowOneCaller_PerMethodName_UnderConcurrentAccess()
129129
{
130-
using var methodLock = new MethodThreadLock();
130+
using var methodLocks = new MethodThreadLocks();
131131
var counter = 0;
132132
var maxObservedConcurrency = 0;
133133
var gate = new object();
134134

135135
async Task Worker()
136136
{
137-
await methodLock.LockAsync(nameof(Worker));
137+
await methodLocks.LockAsync(nameof(Worker));
138138
try
139139
{
140140
lock (gate)
@@ -152,7 +152,7 @@ async Task Worker()
152152
}
153153
finally
154154
{
155-
methodLock.Unlock(nameof(Worker));
155+
methodLocks.Unlock(nameof(Worker));
156156
}
157157
}
158158

‎src/ThunderDesign.Net-PCL.Threading.UnitTests/Locks/MultipleThreadLockManagerTests.cs‎

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -12,31 +12,31 @@ public class MultipleThreadLockManagerTests
1212
[Fact]
1313
public async Task LockAsync_ShouldThrowArgumentNullException_WhenKeyIsNull()
1414
{
15-
using var manager = new MultipleThreadLockManager<string, SingleThreadLock>();
15+
using var manager = new MultipleThreadLocks<string, SingleThreadLock>();
1616

1717
await Assert.ThrowsAsync<ArgumentNullException>(() => manager.LockAsync(null!));
1818
}
1919

2020
[Fact]
2121
public void Unlock_ShouldThrowArgumentNullException_WhenKeyIsNull()
2222
{
23-
using var manager = new MultipleThreadLockManager<string, SingleThreadLock>();
23+
using var manager = new MultipleThreadLocks<string, SingleThreadLock>();
2424

2525
Assert.Throws<ArgumentNullException>(() => manager.Unlock(null!));
2626
}
2727

2828
[Fact]
2929
public void Unlock_ShouldThrowKeyNotFoundException_WhenKeyDoesNotExist()
3030
{
31-
using var manager = new MultipleThreadLockManager<string, SingleThreadLock>();
31+
using var manager = new MultipleThreadLocks<string, SingleThreadLock>();
3232

3333
Assert.Throws<KeyNotFoundException>(() => manager.Unlock("missing-key"));
3434
}
3535

3636
[Fact]
3737
public async Task Unlock_ShouldThrowSynchronizationLockException_WhenKeyLockIsNotHeld()
3838
{
39-
using var manager = new MultipleThreadLockManager<string, SingleThreadLock>();
39+
using var manager = new MultipleThreadLocks<string, SingleThreadLock>();
4040

4141
await manager.LockAsync("key1");
4242
manager.Unlock("key1");
@@ -47,7 +47,7 @@ public async Task Unlock_ShouldThrowSynchronizationLockException_WhenKeyLockIsNo
4747
[Fact]
4848
public async Task LockAsync_ShouldCreateSeparateLocks_ForDifferentKeys()
4949
{
50-
using var manager = new MultipleThreadLockManager<string, SingleThreadLock>();
50+
using var manager = new MultipleThreadLocks<string, SingleThreadLock>();
5151

5252
var lockTask1 = manager.LockAsync("key1");
5353
var lockTask2 = manager.LockAsync("key2");
@@ -61,7 +61,7 @@ public async Task LockAsync_ShouldCreateSeparateLocks_ForDifferentKeys()
6161
[Fact]
6262
public async Task LockAsync_ShouldBlock_ForSameKey_UntilUnlocked()
6363
{
64-
using var manager = new MultipleThreadLockManager<string, SingleThreadLock>();
64+
using var manager = new MultipleThreadLocks<string, SingleThreadLock>();
6565

6666
await manager.LockAsync("shared-key");
6767

@@ -79,7 +79,7 @@ public async Task LockAsync_ShouldBlock_ForSameKey_UntilUnlocked()
7979
[Fact]
8080
public async Task LockAsync_ShouldThrowOperationCanceledException_WhenCancelled()
8181
{
82-
using var manager = new MultipleThreadLockManager<string, SingleThreadLock>();
82+
using var manager = new MultipleThreadLocks<string, SingleThreadLock>();
8383

8484
await manager.LockAsync("key1");
8585

@@ -94,7 +94,7 @@ public async Task LockAsync_ShouldThrowOperationCanceledException_WhenCancelled(
9494
[Fact]
9595
public async Task LockAsync_ShouldThrowObjectDisposedException_WhenManagerIsDisposedWhileWaiting()
9696
{
97-
var manager = new MultipleThreadLockManager<string, SingleThreadLock>();
97+
var manager = new MultipleThreadLocks<string, SingleThreadLock>();
9898

9999
await manager.LockAsync("key1");
100100

@@ -108,7 +108,7 @@ public async Task LockAsync_ShouldThrowObjectDisposedException_WhenManagerIsDisp
108108
[Fact]
109109
public async Task LockAsync_ShouldThrowObjectDisposedException_WhenAlreadyDisposed()
110110
{
111-
var manager = new MultipleThreadLockManager<string, SingleThreadLock>();
111+
var manager = new MultipleThreadLocks<string, SingleThreadLock>();
112112
manager.Dispose();
113113

114114
await Assert.ThrowsAsync<ObjectDisposedException>(() => manager.LockAsync("key1"));
@@ -117,7 +117,7 @@ public async Task LockAsync_ShouldThrowObjectDisposedException_WhenAlreadyDispos
117117
[Fact]
118118
public void Unlock_ShouldThrowObjectDisposedException_WhenAlreadyDisposed()
119119
{
120-
var manager = new MultipleThreadLockManager<string, SingleThreadLock>();
120+
var manager = new MultipleThreadLocks<string, SingleThreadLock>();
121121
manager.Dispose();
122122

123123
Assert.Throws<ObjectDisposedException>(() => manager.Unlock("key1"));
@@ -126,7 +126,7 @@ public void Unlock_ShouldThrowObjectDisposedException_WhenAlreadyDisposed()
126126
[Fact]
127127
public void Dispose_ShouldBeIdempotent()
128128
{
129-
var manager = new MultipleThreadLockManager<string, SingleThreadLock>();
129+
var manager = new MultipleThreadLocks<string, SingleThreadLock>();
130130

131131
manager.Dispose();
132132
var exception = Record.Exception(() => manager.Dispose());
@@ -137,7 +137,7 @@ public void Dispose_ShouldBeIdempotent()
137137
[Fact]
138138
public async Task LockAsync_ShouldOnlyAllowOneThreadPerKey_UnderConcurrentAccess()
139139
{
140-
using var manager = new MultipleThreadLockManager<string, SingleThreadLock>();
140+
using var manager = new MultipleThreadLocks<string, SingleThreadLock>();
141141
var counter = 0;
142142
var maxObservedConcurrency = 0;
143143
var gate = new object();

‎src/ThunderDesign.Net-PCL.Threading.nuspec.in‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
<releaseNotes>See ${{ env.REPOSITORY_URL }}/releases/tag/$version$</releaseNotes>
1414
<tags>${{ env.TAGS }}</tags>
1515
<repository type="git" url="${{ env.REPOSITORY_URL }}" />
16+
<icon>icon.png</icon>
1617
<readme>README.md</readme>
1718
<dependencies>
1819
<!-- Explicitly declare empty groups for netstandard1.x so they don't inherit the Toolkit --> <group targetFramework="netstandard1.0" />
@@ -58,6 +59,9 @@
5859
<!-- The global Analyzer folder (safely guarded by csproj targeting limits) -->
5960
<file src="src/ThunderDesign.Net-PCL.SourceGenerators/bin/Release/netstandard2.0/ThunderDesign.Net-PCL.SourceGenerators.dll" target="analyzers/dotnet/cs/" />
6061

62+
<!-- Include the icon -->
63+
<file src="..\icon.png" target="" />
64+
6165
<!-- Include the README -->
6266
<file src="README.md" target="" />
6367
</files>

0 commit comments

Comments
 (0)