Rx Challenge #11

2016/09/08

no comments

Rx Challenge #11

This challenge is practice of building something already exists, by your own.

The challenge is to build async lock similar to the functionality of SemaphoreSlim WaitAsync / Release.

You can check this post for the functionality of SemaphoreSlim.

You can consider the following building block for this challenge:

Concurrent Collection

Interlocked

TaskCompletionSource

Task, Parallel, Semaphore, WaitAsync, Challenge

You can validate your solution against this Test

Code Snippet
  1. [TestMethod]
  2. public async Task AsyncLock_Test()
  3. {
  4.     // arrange
  5.     const int LIMIT = 3;
  6.     var gate = new TaskCompletionSource<object>();
  7.     var barrier = new CountdownEvent(LIMIT);
  8.     var asyncLock = new AsyncLock(LIMIT);
  9.     var timeout = TimeSpan.FromMinutes(1);
  10.     int aquires = 0;
  11.  
  12.     // Act
  13.     var query = from i in Enumerable.Range(0, LIMIT * 2)
  14.                 select Task.Run(async () =>
  15.                 {
  16.                     try
  17.                     {
  18.                         await asyncLock.WaitAsync();
  19.                         Interlocked.Increment(ref aquires);
  20.                         barrier.Signal();
  21.                         await gate.Task; // doesn't finish until the gate is open
  22.                     }
  23.                     finally
  24.                     {
  25.                         asyncLock.Release();
  26.                     }
  27.                 });
  28.     var tasks = query.ToArray();
  29.  
  30.     // validate
  31.     Assert.IsTrue(barrier.Wait(timeout)); // wait for the  limites tread to be completed
  32.     await Task.Yield(); // give other thread chance to pass the async lock (won't happens)
  33.     Assert.AreEqual(LIMIT, aquires);
  34.  
  35.     barrier.Reset();
  36.     gate.TrySetResult(null); // release the waiting threads
  37.     Assert.IsTrue(barrier.Wait(timeout)); // wait for the  limites tread to be completed
  38.     Assert.AreEqual(LIMIT * 2, aquires);
  39. }

AsyncLock at line 8 is the class provides the solution.

 

The next step is to wrap your solution with Disposable in order to get better usability and replace the try finally block with using block.

You can validate the next step with the following test:

Code Snippet
  1. [TestMethod]
  2. public async Task AsyncLocker_Test()
  3. {
  4.     // arrange
  5.     const int LIMIT = 3;
  6.     var gate = new TaskCompletionSource<object>();
  7.     var barrier = new CountdownEvent(LIMIT);
  8.     var asyncLocker = new AsyncLocker(LIMIT);
  9.     var timeout = TimeSpan.FromMinutes(1);
  10.     int aquires = 0;
  11.  
  12.     // Act
  13.     var query = from i in Enumerable.Range(0, LIMIT * 2)
  14.                 select Task.Run(async () =>
  15.                 {
  16.                     using (await asyncLocker.Acquire())
  17.                     {
  18.                         Interlocked.Increment(ref aquires);
  19.                         barrier.Signal();
  20.                         await gate.Task; // doesn't finish until the gate is open
  21.                     }
  22.                 });
  23.     var tasks = query.ToArray();
  24.  
  25.     // validate
  26.     Assert.IsTrue(barrier.Wait(timeout)); // wait for the  limites tread to be completed
  27.     await Task.Yield(); // give other thread chance to pass the async lock (won't happens)
  28.     Assert.AreEqual(LIMIT, aquires);
  29.  
  30.     barrier.Reset();
  31.     gate.TrySetResult(null); // release the waiting threads
  32.     Assert.IsTrue(barrier.Wait(timeout)); // wait for the  limites tread to be completed
  33.     Assert.AreEqual(LIMIT * 2, aquires);
  34. }

AsyncLocker represent the Disposable wrapping provider over the previous solution (line 8).

It take effect at line 16.

 

All challenges available here.

Add comment
facebook linkedin twitter email

Leave a Reply

Your email address will not be published.

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

*