SemaphoreWrapper/src/ProcessSemaphore_Linux.cpp

132 lines
2.9 KiB
C++
Raw Blame History

This file contains invisible Unicode characters!

This file contains invisible Unicode characters that may be processed differently from what appears below. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to reveal hidden characters.

#ifndef _WIN32 /// Linux
#include "SemaphoreWrapper.h"
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include "log.h"
 
class ProcessSemaphore::impl
{
public:
    int id;
 
    int key;
    int status;
    bool created;
};
 
static void _do_clean_up_semaphore(int key,int id)
{
    if(semctl(id,0,IPC_RMID,0)<0)
    {
        log("Failed to destroy process semaphore (call semctl failed on key: %d, id: %d)",key,id);
    }
}
 
ProcessSemaphore::ProcessSemaphore(int key,int action,int default_value) : _p(new impl)
{
    if(_p)
    {
        _p->key=key;
 
        _p->status=0;
        switch(action)
        {
        case 0:
            _p->id=semget(key,1,0666);
            break;
        case 1:
            _p->id=semget(key,1,0666|IPC_CREAT|IPC_EXCL);
            break;
        }
 
        if(_p->id<0)
        {
            _p->status=0;
        }
        else
        {
            _p->status=1;
 
            if(action==1) /// Created semaphore needs to be initialized
            {
                if(semctl(_p->id,0,SETVAL,1)>=0)
                {
                    _p->status=2;
                    _p->created=true;
                }
            }
            else /// Got a created semaphore
            {
                _p->status=2;
                _p->created=false;
            }
 
            if(_p->status!=2) /// Semaphore does not reach ready level.
            {
                _do_clean_up_semaphore(key,_p->id);
                _p->status=0; /// Set status to empty(0)
            }
        }
    }
}
bool ProcessSemaphore::isReady() const
{
return _p&&_p->status==2;
}
 
int ProcessSemaphore::p()
{
    struct sembuf b;
    b.sem_num=0;
    b.sem_op=-1;
    b.sem_flg=SEM_UNDO;
    if(semop(_p->id,&b,1)<0)
    {
        return -1;
    }
    else return 0;
}
 
int ProcessSemaphore::v()
{
    struct sembuf b;
    b.sem_num=0;
    b.sem_op=1;
    b.sem_flg=SEM_UNDO;
    if(semop(_p->id,&b,1)<0)
    {
        return -1;
    }
    else return 0;
}
 
int ProcessSemaphore::wait()
{
    return p();
}
 
int ProcessSemaphore::notify()
{
    return v();
}
 
ProcessSemaphore::~ProcessSemaphore()
{
    if(_p)
    {
        if(_p->created)
        {
            _do_clean_up_semaphore(_p->key,_p->id);
        }
 
        delete _p;
    }
}
#endif /// End of Linux.