@@ -12,18 +12,77 @@ namespace CodeJam.Threading
1212 [ TestFixture ]
1313 public class AsyncLockTest
1414 {
15+ private static async Task < bool > TryTakeAndHold (
16+ AsyncLock asyncLock , TimeSpan holdTime , CancellationToken cancellation = default ( CancellationToken ) , Action callback = null )
17+ {
18+ try
19+ {
20+ using ( await asyncLock . AcquireAsync ( holdTime , cancellation ) )
21+ {
22+ callback ? . Invoke ( ) ;
23+ await Task . Delay ( holdTime ) ;
24+ }
25+ return true ;
26+ }
27+ catch ( OperationCanceledException )
28+ {
29+ return false ;
30+ }
31+ catch ( TimeoutException )
32+ {
33+ return false ;
34+ }
35+ }
36+
37+ [ Test ]
38+ [ SuppressMessage ( "ReSharper" , "MethodSupportsCancellation" ) ]
39+ public async Task LockCancellationTest ( )
40+ {
41+ var asyncLock = new AsyncLock ( ) ;
42+ var holdTime = TimeSpan . FromSeconds ( 8 ) ;
43+ var delayTime = TimeSpan . FromMilliseconds ( 200 ) ;
44+
45+ var lock1Started = new ManualResetEventSlim ( false ) ;
46+
47+ var lock1 = TryTakeAndHold ( asyncLock , holdTime , callback : ( ) => lock1Started . Set ( ) ) ;
48+ lock1Started . Wait ( ) ;
49+
50+ var cts2 = new CancellationTokenSource ( ) ;
51+ var sw2 = Stopwatch . StartNew ( ) ;
52+ var lock2 = TryTakeAndHold ( asyncLock , holdTime , cts2 . Token ) ;
53+ await Task . Delay ( delayTime ) ;
54+ cts2 . Cancel ( ) ;
55+ var lock2Taken = await lock2 ;
56+ sw2 . Stop ( ) ;
57+
58+ var sw3 = Stopwatch . StartNew ( ) ;
59+ var lock3 = TryTakeAndHold ( asyncLock , delayTime ) ;
60+ await Task . Delay ( delayTime ) ;
61+ var lock3Taken = await lock3 ;
62+ sw3 . Stop ( ) ;
63+
64+ var lock1Taken = await lock1 ;
65+
66+ Assert . IsTrue ( lock1Taken ) ;
67+ Assert . IsFalse ( lock2Taken ) ;
68+ Assert . Less ( sw2 . Elapsed , holdTime - delayTime ) ;
69+ Assert . IsFalse ( lock3Taken ) ;
70+ Assert . Less ( sw3 . Elapsed , holdTime - delayTime ) ;
71+ }
72+
1573 [ Test ]
1674 public async Task LockTest ( )
1775 {
1876 var asyncLock = new AsyncLock ( ) ;
77+
1978 var opActive = false ;
2079 const int time = 200 ;
2180 const int timeInc = 10 ;
2281 const int count = 10 ;
2382
2483 async Task Op ( int num )
2584 {
26- using ( await asyncLock . Acquire ( ) )
85+ using ( await asyncLock . AcquireAsync ( ) )
2786 {
2887 Assert . IsFalse ( opActive ) ;
2988 opActive = true ;
@@ -42,36 +101,5 @@ await Enumerable
42101 Assert . IsFalse ( opActive ) ;
43102 Assert . GreaterOrEqual ( sw . ElapsedMilliseconds , time * count + timeInc * count / 2 ) ;
44103 }
45-
46- [ Test ]
47- [ SuppressMessage ( "ReSharper" , "MethodSupportsCancellation" ) ]
48- public async Task Cancellation ( )
49- {
50- var cts = new CancellationTokenSource ( ) ;
51- var lck = new AsyncLock ( ) ;
52- const int delay = 5000 ;
53- const int ensureLockInterval = 30 ;
54- Task . Run (
55- async ( ) =>
56- {
57- using ( await lck . Acquire ( ) )
58- await Task . Delay ( delay ) ;
59- } ) ;
60- await Task . Delay ( ensureLockInterval ) ;
61- var sw = Stopwatch . StartNew ( ) ;
62- var task = Task . Run (
63- async ( ) =>
64- {
65- using ( await lck . Acquire ( cts . Token ) )
66- sw . Stop ( ) ;
67- } ) ;
68- cts . Cancel ( ) ;
69- try
70- {
71- await task ;
72- }
73- catch ( TaskCanceledException ) { }
74- Assert . Less ( sw . ElapsedMilliseconds , delay - ensureLockInterval ) ;
75- }
76104 }
77105}
0 commit comments