跨进程的CRITICAL_SECTION

critical section问题在windows中可以用CRITICAL_SECTION,mutex之类的解决

mutex可跨进程,但每次PV都要进入内核模式

CRITICAL_SECTION减少了系统调用的次数,但不能跨进程

这里尝试做一个能跨进程并且减少系统调用的次数的同步类


CSLock.h

#ifndef CSLOCK_H_INCLUDED
#define CSLOCK_H_INCLUDED

class CSLock
{
    public:
    enum Disposition{OpenExisting,OpenAlways,CreateNew};
    private:
    typedef struct _LOCK_SHARED_DATA
    {
        LONG Key;
        DWORD OwnerId;
        DWORD SpinCount;
        LONG WaitingCount;
        TCHAR EventName[12];
    }LOCK_SHARED_DATA,*PLOCK_SHARED_DATA;
    DWORD EntryCount;
    HANDLE hSection,hEvent;
    PLOCK_SHARED_DATA SharedData;
    bool Opened;
    bool Create(const TCHAR*Name,CSLock::Disposition CreateDisposition,DWORD SpinCount);
    bool Close();
    public:
    bool Acquire(DWORD Timeout=INFINITE,bool Alertable=false);
    bool Release();
    bool IsOpened()const;
    bool Recreate(const TCHAR*Name,CSLock::Disposition CreateDisposition,DWORD SpinCount=128);
    CSLock(const TCHAR*Name,CSLock::Disposition CreateDisposition=CSLock::OpenAlways,DWORD SpinCount=128);
    ~CSLock();
};

#endif // CSLOCK_H_INCLUDED
#include<windows.h>
#include<tchar.h>
#include"CSLock.h"
//#include<stdio.h>
const TCHAR DefEventName[]=TEXT("ovaltransferrin");

bool CSLock::Create(const TCHAR*Name,CSLock::Disposition CreateDisposition,DWORD SpinCount)
{
    DWORD NameLength,MappingSize;
    NameLength=Name?_tcslen(Name):sizeof(DefEventName)-sizeof(TCHAR);
    MappingSize=sizeof(LOCK_SHARED_DATA)+NameLength*sizeof(TCHAR);
    if(CreateDisposition==CSLock::OpenExisting)
        this->hSection=OpenFileMapping(FILE_MAP_WRITE,FALSE,Name);
    else
        this->hSection=CreateFileMapping(INVALID_HANDLE_VALUE,NULL,PAGE_READWRITE|SEC_COMMIT,0,MappingSize,Name);
    if(this->hSection)
    {
        bool AlreadyExists=(GetLastError()==ERROR_ALREADY_EXISTS)||(CreateDisposition==CSLock::OpenExisting);
        if(CreateDisposition==CSLock::CreateNew&&AlreadyExists)
        {
            CloseHandle(this->hSection);
            return false;
        }
        this->SharedData=static_cast<CSLock::PLOCK_SHARED_DATA>(MapViewOfFileEx(this->hSection,FILE_MAP_WRITE,0,0,0,NULL));
        if(this->SharedData)
        {
            if(!AlreadyExists)
            {
                SYSTEM_INFO sysinfo;
                GetSystemInfo(&sysinfo);
                this->SharedData->Key=1;
                this->SharedData->OwnerId=0;
                this->SharedData->SpinCount=sysinfo.dwNumberOfProcessors>1?SpinCount:0;
                this->SharedData->WaitingCount=0;
                _tcscpy(this->SharedData->EventName,Name?Name:DefEventName);
                for(int tryc=0;tryc<255;++tryc)
                {
                    FILETIME systime;
                    GetSystemTimeAsFileTime(&systime);
                    _ultot(systime.dwLowDateTime+systime.dwHighDateTime,this->SharedData->EventName+NameLength,16);
                    this->hEvent=CreateEvent(NULL,TRUE,FALSE,this->SharedData->EventName);
                    if(this->hEvent&&GetLastError()==ERROR_ALREADY_EXISTS)
                    {
                        CloseHandle(this->hEvent);
                    }else if(GetLastError()!=ERROR_ACCESS_DENIED)return true;
                }
            }else
            {
                this->hEvent=OpenEvent(SYNCHRONIZE,FALSE,this->SharedData->EventName);
                if(this->hEvent)return true;
            }
            UnmapViewOfFile(this->SharedData);
        }
    }
    return false;
}

bool CSLock::Acquire(DWORD Timeout,bool Alertable)
{
    if(this->SharedData->OwnerId!=GetCurrentThreadId())
    {
        DWORD i(this->SharedData->SpinCount);
        InterlockedIncrement(&this->SharedData->WaitingCount);
        while(InterlockedExchange(&this->SharedData->Key,0)==0&&i--);
        if(i==DWORD(-1))
        {
            if(Timeout==0)
            {
                InterlockedDecrement(&this->SharedData->WaitingCount);
                return false;
            }
            do
            {
                DWORD r=WaitForSingleObjectEx(this->hEvent,Timeout,Alertable);
                if(r==WAIT_OBJECT_0)
                {
                    if(InterlockedExchange(&this->SharedData->Key,0))
                    {
                        ResetEvent(this->hEvent);
                        break;
                    }
                }else
                {
                    InterlockedDecrement(&this->SharedData->WaitingCount);
                    return false;
                }
            }while(1);
        }
        InterlockedDecrement(&this->SharedData->WaitingCount);
        this->SharedData->OwnerId=GetCurrentThreadId();
    }
    ++this->EntryCount;
    return true;
}

bool CSLock::Release()
{
    if(this->SharedData->OwnerId==GetCurrentThreadId())
    {
        if(--this->EntryCount==0)
        {
            this->SharedData->OwnerId=0;
            InterlockedExchange(&this->SharedData->Key,1);
            if(InterlockedCompareExchange(&this->SharedData->WaitingCount,0,0))SetEvent(this->hEvent);
        }
        return true;
    }
    return false;
}

bool CSLock::IsOpened()const
{
    return this->Opened;
}

bool CSLock::Close()
{
    if(this->Opened)
    {
        CloseHandle(this->hEvent);
        UnmapViewOfFile(this->SharedData);
        CloseHandle(this->hSection);
        this->Opened=false;
        return true;
    }else return false;
}

bool CSLock::Recreate(const TCHAR*Name,CSLock::Disposition CreateDisposition,DWORD SpinCount)
{
    CSLock::Close();
    return CSLock::Create(Name,CreateDisposition,SpinCount);
}

CSLock::CSLock(const TCHAR*Name,CSLock::Disposition CreateDisposition,DWORD SpinCount):EntryCount(0),Opened(CSLock::Create(Name,CreateDisposition,SpinCount))
{

}

CSLock::~CSLock()
{
    CSLock::Close();
}


main.cpp

#include <iostream>
#include <windows.h>
#include <conio.h>
#include "CSLock.h"
using namespace std;

int main()
{
    CSLock c("x");
    cout<<"opened:"<<c.IsOpened()<<endl;
    c.Acquire();
    cout << "pid:"<<GetCurrentProcessId() << endl;
    getch();
    c.Release();
    cout<<"quit"<<endl;
    getch();
    return 0;
}


你可能感兴趣的:(windows,struct,object,File,null,Access)