一个跨平台的单列Singletonlnst的实现

来源:互联网 发布:红黑树java实现 编辑:程序博客网 时间:2024/04/29 22:30

#if !defined(SINGLEONINST_H_)
#define SINGLEONINST_H_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

#include "hstring.h"

//////////////////////////////////////////////////////////////////////////
// CSingletonInst

class CSingletonInst
{
// Constructions
public:
    CSingletonInst(LPCSTR lpszInstName);
    ~CSingletonInst();
   
private:
    CSingletonInst();
    CSingletonInst(const CSingletonInst &);
    CSingletonInst & operator = (const CSingletonInst &);

// Operations
public:
    BOOL TryRun(CHString &strErr);
   
// Member
private:
    char m_szInstName[512];
   
#ifdef WIN32
    HANDLE m_hMutex;
#endif
};

#endif // SINGLEONINST_H_

 ---------------------------------------------------

 

//////////////////////////////////////////////////////////////////////////
// CSingletonInst

CSingletonInst::CSingletonInst(LPCSTR lpszInstName)
{
    COM_ASSERT(NULL != lpszInstName);
   
    SAFE_STRCPY(m_szInstName, lpszInstName);

#ifdef WIN32
    m_hMutex = NULL;
#endif
}

CSingletonInst::~CSingletonInst()
{
#ifdef WIN32
    if (NULL != m_hMutex)
    {
        ::CloseHandle(m_hMutex); //lint !e534 ignored the return value, not care
        m_hMutex = NULL;
    }
#endif
}

BOOL CSingletonInst::TryRun(CHString &strErr)
{
    strErr = "";

#ifdef WIN32
    //////////////////////////////////////////////////////////////////////////
    // WIN32 implementation start
    CHString strMutexName = m_szInstName;
    strMutexName += "SINGLETON_INST";
    strMutexName.MakeUpper();
    m_hMutex = ::CreateMutex(NULL, TRUE, strMutexName);
    if (NULL != m_hMutex)
    {
        if (ERROR_ALREADY_EXISTS == GetLastError())
        {
            strErr = "another instance running";
            return FALSE;
        }
    }

    return TRUE;
    // WIN32 implementation end
    //////////////////////////////////////////////////////////////////////////

#else // !WIN32
    //////////////////////////////////////////////////////////////////////////
    // !WIN32 implementation start
    CHString strInstFile;
    strInstFile.Format("%s/.%s_pidfile",
        (LPCTSTR)GetBinPath(),
        (LPCTSTR)m_szInstName
        );

    int fd = open(strInstFile, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
    if (fd < 0)
    {
        strErr.Format("open pid file failed. file=%s.",
            (LPCSTR)strInstFile
            );
        return FALSE;
    }

    // File record locking structure used by fcntl()
    struct flock   flk;
    flk.l_type   = F_WRLCK;  // F_RDLCK, F_WRLCK, or F_UNLCK
    flk.l_whence = SEEK_SET; // SEEK_SET, SEEK_CUR, SEEK_END
    flk.l_start  = 0;        // starting offset relative to l_whence
    flk.l_len    = 0;        // len == 0 means "until end of file
    flk.l_pid    = getpid(); // Process ID of the process holding the lock, returned with F_GETLK
    if (fcntl(fd, F_SETLK, &flk) < 0)
    {
        if ((EAGAIN == errno)
            || (EACCES == errno)
            )
        {
            strErr = "another instance running";
        }
        else
        {
            strErr.Format("lock pid file failed. file=%s",
                (LPCTSTR)strInstFile
                );
        }

        return FALSE;
    }

    // write pid to file
    ftruncate(fd, 0);
    char szpid[48] = {0};
    sprintf(szpid, "%u", getpid());
    write(fd, szpid, strlen(szpid));

    return TRUE;
    // !WIN32 implementation end
    //////////////////////////////////////////////////////////////////////////
#endif // !WIN32
}

//lint -restore

 

备注:在wondows下是通过互斥量来实现的。

 linux下是通过对文件加锁。当另一个相同的进程启动时,获取锁失败。

    通过获得失败标志。进而进行退出处理(这部分在这里没有写出来)。

    在这里提供一种思路。


 

 

 

 

 

 

0 0
原创粉丝点击