Use Semaphores as Global Counters.

4 04 2008

Icon Description
For certain instance, we need global counters which can be accessed from any process. For instance how many instance of application is running or if our application wants to expose some values such as its performance figures etc. We can use Semaphores as global counters.

Icon How Can I Do It?
Actually semaphore is meant for synchronization. But unlike other synchronization objects like mutex or event, semaphore can hold a count in it. And like other Kernel objects, semaphore can have a name which makes it possible to be accessed from any process across the system. We are going to utilize these properties to transform it as a Global Counter.

Create Global Counter.
Function CreateSemaphore() is Used to create the semaphore. While Creating, you can specify an initial count, a maximum count and a name. The name is used for opening the same semaphore from other applications.

Accessing Global Counter.
Function CreateSemaphore() is again used to access the existing semaphore. If the semaphore exists, the function returns a new handle to the semaphore. OpenSemaphore() also can be used.

Incrementing Global Counter.
Function ReleaseSemaphore() can be used. Actually this function is used to increment the semaphore value and there by signal a thread, which is waiting for the semaphore. But, we use this function to increment the value.

Decrementing Global Counter.
Function WaitForSingleObject() can be used. Threads uses this function to wait on semaphores until it get signled. Once signled, WaitForSingleObject decrements the semaphore count. So this is used to decrement the value of Global Counter. But a single call to WaitForSingleObject() will decrease the value by one only. So we’ve to call the WaitForSingleObject() number of times to decrement numbers greater than one.

Reading Global Counter.
Function ReleaseSemaphore() can be used again. It returns the current value. Since ReleaseSemaphore() increment the semaphore value, we’ve to call WaitForSingleObject() once again to normalize the value of semaphore.

For simplicity, i’ve implemented the logic in a class named CGlobalCounter.

class CGlobalCounter
{
public:
// Constructor and Destructor.
CGlobalCounter( const TCHAR* strGlobalCounterName );
~CGlobalCounter();

// Initialize counter.
bool Initialize();

// Increment and Decrement.
void Increment( LONG lIncrementBy );
void Decrement( LONG lDecrementBy );

// Get the Value.
LONG GetValue();

private:
HANDLE m_hGlobalCounter;  // Handle for semaphore.
CString m_csGlobalCounterName; // Semaphore name.
};

Download sample from here. Right click and Save to your harddisk and rename to .zip. Since there are some limitation in file uploading, i can’t upload zip files.

Icon Note
Advantages
1) Very simple to use.
2) less resource usage.

Disadvantage
1) Since the GetValue() – increment and decrement semaphore, the GlobalCounter can hold only upto MaxValue-1.
2) While decrementing, there can be a performance bottleneck.

Decide yourself whether you need it or not.
Quite lengthy one, but its worthy. 😉


Targeted Audience – Advanced.

Advertisements