first commit

master
Kirigaya Kazuto 2017-12-25 15:48:41 +08:00
commit 9f4639e6ec
7 changed files with 302 additions and 0 deletions

6
.gitignore vendored Normal file
View File

@ -0,0 +1,6 @@
bin/
obj/
*.cbp
*.layout
*.depend

View File

@ -0,0 +1,17 @@
#pragma once
class ProcessSemaphore
{
public:
/// action: 0 MustGet 1 MustCreateNew
ProcessSemaphore(int key,int action=0,int default_value=1);
bool isReady() const;
int p(); /// wait
int v(); /// notify
int wait(); /// p
int notify(); /// v
~ProcessSemaphore();
private:
class impl;
impl* _p;
};

4
include/log.h Normal file
View File

@ -0,0 +1,4 @@
#pragma once
/// Debug output
void dprintf(const char* fmt,...);

View File

@ -0,0 +1,131 @@
#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.

View File

@ -0,0 +1,93 @@
#include "SemaphoreWrapper.h"
#include <windows.h>
#include <cstdio>
class ProcessSemaphore::impl
{
public:
HANDLE h;
int status;
};
ProcessSemaphore::ProcessSemaphore(int key, int action, int default_value) : _p(new impl)
{
if(_p)
{
_p->status=0;
char buff[64];
memset(buff,0,64);
sprintf(buff,"LibSemaphoreWrapper_%d",key);
_p->h=CreateSemaphore(NULL,default_value,default_value,buff);
if(_p->h==NULL)
{
_p->status=0;
}
else
{
if(action==1&&(GetLastError()==ERROR_ALREADY_EXISTS))
{
CloseHandle(_p->h);
_p->status=0;
}
else
{
_p->status=1;
}
}
}
}
bool ProcessSemaphore::isReady() const
{
return _p&&_p->status==1;
}
int ProcessSemaphore::p()
{
DWORD ret=WaitForSingleObject(_p->h,INFINITE);
if(ret==WAIT_OBJECT_0)
{
return 0;
}
else if(ret==WAIT_TIMEOUT)
{
return -1;
}
else
{
return -2;
}
}
int ProcessSemaphore::v()
{
ReleaseSemaphore(_p->h,1,NULL);
return 0;
}
int ProcessSemaphore::wait()
{
return p();
}
int ProcessSemaphore::notify()
{
return v();
}
ProcessSemaphore::~ProcessSemaphore()
{
if(_p)
{
if(isReady())
{
CloseHandle(_p->h);
}
delete _p;
}
}

19
src/log.cpp Normal file
View File

@ -0,0 +1,19 @@
#include "log.h"
#include <cstdarg>
#include <cstdio>
using namespace std;
#ifdef DEBUG
void dprintf(const char* fmt,...)
{
va_list ap;
va_start(ap,fmt);
vprintf(fmt,ap);
va_end(ap);
}
#else
void dprintf(const char* fmt,...)
{
}
#endif

32
test_main.cpp Normal file
View File

@ -0,0 +1,32 @@
#include "SemaphoreWrapper.h"
#include <iostream>
using namespace std;
int main()
{
cout<<"Program Started."<<endl;
ProcessSemaphore s(666,1,2);
cout<<"Status: "<<s.isReady()<<endl;
if(!s.isReady())
{
cout<<"Failed to create. Stop."<<endl;
return 0;
}
cout<<"Start P"<<endl;
s.p();
cout<<"Done P"<<endl;
string x;
getline(cin,x);
cout<<"Start V"<<endl;
s.v();
cout<<"Done V"<<endl;
cout<<"Program Finished. Press any key."<<endl;
getline(cin,x);
return 0;
}