// Semaphore.h V0.1pre - Provides class Semaphore (Binary & Counting) member functions
// © 2003 Elliot Nierman

 

// Semaphore( )
// Default Constructor, instantiates a binary semaphore with an initial
// count of one, and as binary semaphores go, a maximum count of one
Semaphore::Semaphore()
{
#ifdef WIN
        sem = CreateSemaphore(NULL, 1, 1, NULL);
#endif

#ifdef POSIX
        p_sem = semget (IPC_PRIVATE, 1, (IPC_CREAT | IPC_EXCL | 0400));
        options.val = 1;
        count = 1;
        semctl(p_sem, 0, SETVAL, options);
#endif

}

// Semaphore( long initial_count )
// Overloaded constructor. initializes a semaphore with an initial count
// as well as a maximum count indicated by initial_count. If initial_count
// is zero, then a semaphore with an initial count of zero with a maximum
// count of one is instantiated(Binary Semaphore)
Semaphore::Semaphore(long initial_count)
{

#ifdef WIN
        if(initial_count != 0)
            sem = CreateSemaphore(NULL, initial_count, initial_count, NULL);
        else
            sem = CreateSemaphore(NULL, 0, 1, NULL);
#endif

#ifdef POSIX
        p_sem = semget (IPC_PRIVATE, 1, (IPC_CREAT | IPC_EXCL | 0400));

        options.val = initial_count;
        if (initial_count != 0)
            count = initial_count;
        else
            count = 1;
        semctl(p_sem, 0, SETVAL, options);


#endif


}

// Semaphore(long initial_count, long max_count
// Overloaded constructor which creates a semaphore with an initial
// count specified by initial_count and a maximum count specified
// by max_count
Semaphore::Semaphore(long initial_count, long max_count)
{

#ifdef WIN
        sem = CreateSemaphore(NULL, initial_count, max_count, NULL);

#endif

#ifdef POSIX

        p_sem = semget (IPC_PRIVATE, 1, (IPC_CREAT | IPC_EXCL | 0400));

        options.val = initial_count;
        count = max_count;
        count = 1;
        semctl(p_sem, 0, SETVAL, options);


#endif


}


// Post( )
// If the integer count associated with the semaphore is less than
// the specified maximum count, the count is incremented by one
void Semaphore::Post()
{
#ifdef WIN
        ReleaseSemaphore(sem, 1, NULL);
#endif

#ifdef POSIX

        if (semctl(p_sem, 0, GETVAL, 0) < count)
        {
            action.sem_num = 0;
            action.sem_op = 1;
            action.sem_flg = 0;
            semop(p_sem, &action, 1);
        }
#endif

}


// Wait()
// If Semaphore count is non-zero the thread decrements the count and continues
// execution, otherwise the thread is blocked until the count becomes non-zero.
void Semaphore::Wait()
{
#ifdef WIN
        WaitForSingleObject(sem,INFINITE);
#endif

#ifdef POSIX
        action.sem_num = 0;
        action.sem_op = -1;
        action.sem_flg = 0;
        semop (p_sem, &action, 1);
#endif

}

//~Semaphore()
// Destructor, frees system resources
Semaphore::~Semaphore()
{
#ifdef WIN
        CloseHandle(sem);
#endif

#ifdef POSIX
        semctl(p_sem, 0, IPC_RMID, 0);
#endif

}