-//--------------------------------------------------------------------------\r
-// \r
-// Copyright (c) Microsoft Corporation. All rights reserved. \r
-// \r
-// File: concrt_extras.h\r
-//\r
-// Implementation of ConcRT helpers\r
-//\r
-//--------------------------------------------------------------------------\r
-\r
-#pragma once\r
-\r
-#include <concrt.h>\r
-#include <concurrent_queue.h>\r
-\r
-namespace Concurrency\r
-{ \r
- class semaphore\r
- {\r
- public:\r
- explicit semaphore(LONG capacity)\r
- : _semaphore_count(capacity)\r
- {\r
- }\r
-\r
- // Acquires access to the semaphore.\r
- void acquire()\r
- {\r
- // The capacity of the semaphore is exceeded when the semaphore count \r
- // falls below zero. When this happens, add the current context to the \r
- // back of the wait queue and block the current context.\r
- if (InterlockedDecrement(&_semaphore_count) < 0)\r
- {\r
- _waiting_contexts.push(Concurrency::Context::CurrentContext());\r
- Concurrency::Context::Block();\r
- }\r
- }\r
-\r
- // Releases access to the semaphore.\r
- void release()\r
- {\r
- // If the semaphore count is negative, unblock the first waiting context.\r
- if (InterlockedIncrement(&_semaphore_count) <= 0)\r
- {\r
- // A call to acquire might have decremented the counter, but has not\r
- // yet finished adding the context to the queue. \r
- // Create a spin loop that waits for the context to become available.\r
- Concurrency:: Context* waiting = NULL;\r
- while(!_waiting_contexts.try_pop(waiting))\r
- {\r
- Concurrency::wait(0);\r
- }\r
-\r
- // Unblock the context.\r
- waiting->Unblock();\r
- }\r
- }\r
-\r
- private:\r
- // The semaphore count.\r
- LONG _semaphore_count;\r
-\r
- // A concurrency-safe queue of contexts that must wait to \r
- // acquire the semaphore.\r
- Concurrency::concurrent_queue<Concurrency::Context*> _waiting_contexts;\r
- \r
- semaphore const &operator =(semaphore const&); // no assignment operator\r
- semaphore(semaphore const &); // no copy constructor\r
- };\r
-}
\ No newline at end of file