commit 9f4639e6ec094070045644c71d71e043541d6696 Author: kiritow <1362050620@qq.com> Date: Mon Dec 25 15:48:41 2017 +0800 first commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..47defec --- /dev/null +++ b/.gitignore @@ -0,0 +1,6 @@ +bin/ +obj/ +*.cbp +*.layout +*.depend + diff --git a/include/SemaphoreWrapper.h b/include/SemaphoreWrapper.h new file mode 100644 index 0000000..acf634b --- /dev/null +++ b/include/SemaphoreWrapper.h @@ -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; +}; diff --git a/include/log.h b/include/log.h new file mode 100644 index 0000000..1167e53 --- /dev/null +++ b/include/log.h @@ -0,0 +1,4 @@ +#pragma once + +/// Debug output +void dprintf(const char* fmt,...); diff --git a/src/ProcessSemaphore_Linux.cpp b/src/ProcessSemaphore_Linux.cpp new file mode 100644 index 0000000..c00a973 --- /dev/null +++ b/src/ProcessSemaphore_Linux.cpp @@ -0,0 +1,131 @@ +#ifndef _WIN32 /// Linux +#include "SemaphoreWrapper.h" + +#include +#include +#include +#include +#include +#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. diff --git a/src/ProcessSemaphore_Windows.cpp b/src/ProcessSemaphore_Windows.cpp new file mode 100644 index 0000000..143a080 --- /dev/null +++ b/src/ProcessSemaphore_Windows.cpp @@ -0,0 +1,93 @@ + +#include "SemaphoreWrapper.h" +#include +#include + +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; + } +} diff --git a/src/log.cpp b/src/log.cpp new file mode 100644 index 0000000..3a78541 --- /dev/null +++ b/src/log.cpp @@ -0,0 +1,19 @@ +#include "log.h" +#include +#include +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 diff --git a/test_main.cpp b/test_main.cpp new file mode 100644 index 0000000..955062f --- /dev/null +++ b/test_main.cpp @@ -0,0 +1,32 @@ +#include "SemaphoreWrapper.h" +#include +using namespace std; +int main() +{ + cout<<"Program Started."<