1 //--------------------------------------------------------------------------
\r
3 // Copyright (c) Microsoft Corporation. All rights reserved.
\r
5 // File: concrt_extras.h
\r
7 // Implementation of ConcRT helpers
\r
9 //--------------------------------------------------------------------------
\r
14 #include <concurrent_queue.h>
\r
16 namespace Concurrency
\r
21 explicit semaphore(LONG capacity)
\r
22 : _semaphore_count(capacity)
\r
26 // Acquires access to the semaphore.
\r
29 // The capacity of the semaphore is exceeded when the semaphore count
\r
30 // falls below zero. When this happens, add the current context to the
\r
31 // back of the wait queue and block the current context.
\r
32 if (InterlockedDecrement(&_semaphore_count) < 0)
\r
34 _waiting_contexts.push(Concurrency::Context::CurrentContext());
\r
35 Concurrency::Context::Block();
\r
39 // Releases access to the semaphore.
\r
42 // If the semaphore count is negative, unblock the first waiting context.
\r
43 if (InterlockedIncrement(&_semaphore_count) <= 0)
\r
45 // A call to acquire might have decremented the counter, but has not
\r
46 // yet finished adding the context to the queue.
\r
47 // Create a spin loop that waits for the context to become available.
\r
48 Concurrency:: Context* waiting = NULL;
\r
49 while(!_waiting_contexts.try_pop(waiting))
\r
51 Concurrency::wait(0);
\r
54 // Unblock the context.
\r
60 // The semaphore count.
\r
61 LONG _semaphore_count;
\r
63 // A concurrency-safe queue of contexts that must wait to
\r
64 // acquire the semaphore.
\r
65 Concurrency::concurrent_queue<Concurrency::Context*> _waiting_contexts;
\r
67 semaphore const &operator =(semaphore const&); // no assignment operator
\r
68 semaphore(semaphore const &); // no copy constructor
\r