Synchronization

本文介绍了一种使用互斥锁、事件和信号量实现的同步机制,包括这些机制的类实现及生产者消费者模型示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Well, in the really world, there are so many things you have to wait for, my wages up, my promotion, my princess…and those things never send me a signal. Wait for single object seems to be disparate and hopeless, while wait for multiple objects seems better. While in my code, I am the GOD, I can do anything I want with my code. To some extent programming satisfied one’s desire for governing and controlling. Well I went too far away. Let me go back to the subject.

 

There are many ways to implement synchronization: event, mutex, critical section, semaphore.

Every object has it’s own advantage, such as event can be used for both sync and notification, mutex and event can be used across processes, critical section is easy to use, semaphore can manage more than one resource, and so on. So many details, using them seems to be a big trouble.

 

Here a synchronization class is introduced to handle those problems:

 

Here is the code:

#include <windows.h>

 

//---------------------------- CLASS ----------------------------------------------------------

// Implementation of the critical section

class QMutex {

private:

    CRITICAL_SECTION  m_Cs;

 

public:

    QMutex() { ::InitializeCriticalSection(&this->m_Cs); }

    ~QMutex() { ::DeleteCriticalSection(&this->m_Cs); }

    void Lock() { ::EnterCriticalSection(&this->m_Cs); }

    BOOL TryLock() { return (BOOL) ::TryEnterCriticalSection(&this->m_Cs); }

    void Unlock() { ::LeaveCriticalSection(&this->m_Cs); }

};

 

// Implementation of the event for notify

class QEvent {

private:

    HANDLE     m_Cs;

 

public:

    QEvent() { m_Cs = ::CreateEvent(NULL, FALSE, TRUE, "NotifyEvent"); }

    ~QEvent() { ::CloseHandle(m_Cs); }

    void wait() { ::WaitForSingleObject(this->m_Cs, INFINITE); }

    //BOOL TryLock() { return (BOOL) ::TryEnterCriticalSection(&this->m_Cs); }

    void notify() { ::SetEvent(this->m_Cs); }

};

 

 

//---------------------------- CLASS ----------------------------------------------------------

// Implementation of the semaphore

class QSemaphore {

private:

    HANDLE m_hSemaphore;

    long m_lMaximumCount;

 

public:

    QSemaphore(long lInitialCount, long lMaximumCount) {

       this->m_hSemaphore = ::CreateSemaphore(NULL, lInitialCount, lMaximumCount, NULL);

 

       if (this->m_hSemaphore == NULL) throw "Call to CreateSemaphore() failed. Could not create semaphore.";

       this->m_lMaximumCount = lMaximumCount;

    };

 

    ~QSemaphore() { ::CloseHandle(this->m_hSemaphore); };

 

    long GetMaximumCount() const { return this->m_lMaximumCount; };

    void Inc() { ::WaitForSingleObject(this->m_hSemaphore, INFINITE); };

    void Dec() { ::ReleaseSemaphore(this->m_hSemaphore, 1, NULL); };

    void Dec(long lCount) { ::ReleaseSemaphore(this->m_hSemaphore, lCount, NULL); };

};

 

With the class, here is a example of Producer/Consumer model.

const int RESOURCE_NUM = 2;

QSemaphore g_pFullQSemaphore(0, RESOURCE_NUM);

QSemaphore g_pEmptyQSemaphore(RESOURCE_NUM, RESOURCE_NUM);

 

QMutex g_BufStatusQMutex;   // sync the buffer status

const int ERROR_BUF_INDEX = -1;

BOOL   g_aBufStatus[RESOURCE_NUM] = {0};  // TRUE for full; FALSE for empty

 

// get an empty buffer

int getEmptyIndex()

{

    return FALSE == g_aBufStatus[0] ? 0 :

         (FALSE == g_aBufStatus[1] ? 1 : -1);

}

 

// get a full buffer

int getFullIndex()

{

    return TRUE == g_aBufStatus[0] ? 0 :

         (TRUE == g_aBufStatus[1] ? 1 : -1); 

}

 

void setBufState(int iBufIndex, BOOL bState)

{

    g_BufStatusQMutex.Lock();

    g_aBufStatus[iBufIndex] = bState;

    g_BufStatusQMutex.Unlock();

}

 

DWORD WINAPI ProduceThread(LPVOID lpParameter)

{

 

    //  1.  record ReadRecordThreadInfo

    ReadRecordThreadInfo *pThInof = (ReadRecordThreadInfo *)lpParameter;

    apBuf[0] = pThInof->pBufA;

    apBuf[1] = pThInof->pBufB;

    PriorityST *pPriorityST = pThInof->pPriorityST;

    CDlg *p_this = (CDlg *)pThInof->pDialog;

 

    while (TRUE) {

 

       // get free buffer

       int iBufIndex = -1;  // indicate the free buffer

 

       g_pEmptyQSemaphore.Inc();

 

       if (ERROR_BUF_INDEX == (iBufIndex = getEmptyIndex()))

           continue;

 

       // produce data

       int iRecordCount = 0;

       iRecordCount = pClass->getAllRecord(apBuf[iBufIndex], iEmmCount, pPriorityST);

       if (iRecordCount != iEmmCount)

           break;

 

       // notify send thread

       setBufState(iBufIndex, TRUE);

       g_pFullQSemaphore.Dec();

       Sleep(0);

    }

 

    return 0;

}

 

DWORD WINAPI consumeThread(LPVOID lpParameter)

{

    //  1.  record ReadRecordThreadInfo

    ReadRecordThreadInfo *pThInof = (ReadRecordThreadInfo *)lpParameter;

    apBuf[0] = pThInof->pBufA;

    apBuf[1] = pThInof->pBufB;

    PriorityST *pPriorityST = pThInof->pPriorityST;

    CDlg *p_this = (CDlg *)pThInof->pDialog;

 

    while (TRUE) {

 

       int iBufIndex = -1;

 

       g_pFullQSemaphore.Inc();

 

       if (ERROR_BUF_INDEX == (iBufIndex = getFullIndex()))

           continue;

 

 

       // consume the data

       for (int j = 0; j < iEmmCount; ++j, ++iCountSended) {

           //....

       }

       setBufState(iBufIndex, FALSE);

 

       g_pEmptyQSemaphore.Dec();

       Sleep(0);

    }

 

    return 0;

}

 

// start thread

void CEmmGeneratorDlg::OnBnClickedButtonBegin()

{

    // TODO: Add your control notification handler code here

    static ReadRecordThreadInfo ThInof;

    ThInof.iEmmCount = 30;

    ThInof.pBufA = new EmmMessage[ThInof.iEmmCount];

    ThInof.pBufB = new EmmMessage[ThInof.iEmmCount];

    ThInof.pDialog = this;

 

    HANDLE hTheadR = CreateThread(NULL, 0, readEmmThread, (LPVOID)&ThInof, NULL, NULL);

    HANDLE hTheadW = CreateThread(NULL, 0, sendEmmThread, (LPVOID)&ThInof, NULL, NULL);

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值