Search This Blog

Wednesday, May 25, 2005

Semaphore - Part 3

And lastly, the POSIX semaphore version. As I mentioned last post, I decided to use XSI-style semaphores, rather than the newer semaphores option. Since everything is supported by the OS, all we need to do is wrap the functions; this will be very straightforward. The class:

class CSemaphore // POSIX version of CSemaphore: XSI semaphore (slow)
{
private:
int m_iSem; // Semaphore index

inline int &GetSemaphore()
{
return m_iSem;
}

public:
inline CSemaphore(long nInitialCount)
{
assert(nInitialCount >= 0);

semun ctl;
ctl.val = nCount;
assert(ctl.val == nInitialCount);

// Create the semaphore
m_iSem = semget(IPC_PRIVATE, 1, S_IRUSR | S_IWUSR);
if (m_iSem <= 0)
throw bad_alloc("Unable to create semaphore");

// Initialize the semaphore count
verify(semctl(m_iSem, 0, SETVAL, ctl) == 0);
}
inline ~CSemaphore()
{
verify(semctl(m_iSem, 0, IPC_RMID) == 0);
}

inline bool TryWait()
{
sembuf op;

op.sem_num = 0;
op.sem_op = -1;
op.sem_flg = IPC_NOWAIT; // Don't wait if we can't lock it now

return (semop(m_iSem, &op, 1) == 0);
}

inline void Wait()
{
sembuf op;

op.sem_num = 0;
op.sem_op = -1;
op.sem_flg = 0; // Wait if necessary

verify(semop(m_iSem, &op, 1) == 0);
}

inline void Post(long nCount = 1)
{
assert(nCount > 0);

sembuf op;

op.sem_num = 0;
op.sem_op = nCount;
op.sem_flg = 0;

assert(op.sem_op == nCount); // Make sure there wasn't any truncation
verify(semop(m_iSem, &op, 1) == 0);
}
};

No comments: