Creating the AsyncSemaphore

Let's add a new folder called Threading to the FileStorage.Portable project. Inside this folder, we are going to add a new file called AsyncSemaphore.cs and implement the first part as follows:

public class AsyncSemaphore
    {
        private readonly static Task s_completed = Task.FromResult(true);
        private readonly Queue<TaskCompletionSource<bool>> m_waiters = new Queue<TaskCompletionSource<bool>>();
        private int m_currentCount;
        public AsyncSemaphore(int initialCount)
        {
           if (initialCount < 0) throw new ArgumentOutOfRangeException("initialCount");
           m_currentCount = initialCount; 
        }
        public Task WaitAsync()
        {
           lock (m_waiters)
            {
               if (m_currentCount > 0)
                 {
                    --m_currentCount;
                    return s_completed;
                 }
               else
                {
                   var waiter = new TaskCompletionSource<bool>();
                   m_waiters.Enqueue(waiter); return waiter.Task;
                }
         }
      }
}

Note

A SemaphoreSlim object is used to limit the number of threads that can access a resource.

The AsyncSemaphore keeps a count (the m_count property), which is the number of open slots it has available to satisfy waiters.

The Task returned from the WaitAsync function (the static s_completed property) will enter the completed state when the AsyncSemaphore has given it an available slot. That same Task will enter the Canceled state if the CancellationToken is signaled before the wait is satisfied; in that case, the AsyncSemaphore does not lose a slot.

Note

A waiter is simply a TaskCompletionSource of type bool. It contains a Task, which is the operation to be performed by a single thread.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.191.174.168