windows核心编程用户模式下的线程同步

来源:互联网 发布:淘宝卖家电话采集 编辑:程序博客网 时间:2024/05/16 09:41

前几天草草地看了下源代码,有些地方没太懂就继续了,这里把Queue示例程序分析下吧,毕竟到时候会直接用到作者给的代码

对话框入口函数

int WINAPI _tWinMain(HINSTANCE hinstExe, HINSTANCE, PTSTR pszCmdLine, int) {   DialogBox(hinstExe, MAKEINTRESOURCE(IDD_QUEUE), NULL, Dlg_Proc);   StopProcessing();//注意下IDD_QUEUE是在资源文件rc中记录对话框界面信息的   return(0);}

对话框回调函数

INT_PTR WINAPI      Dlg_Proc(HWND hWnd, UNIT uMsg, WPARAM wParam, lParam){    switch (uMsg){        chHANDLE_DLGMSG(hWnd, WM_INITDIALOG, Dlg_OnInitDialog);        chHANDLE_DLGMSG(hWnd, WM_COMMAND, Dlg_OnCommand);    }}

Dlg_OnCommand

Dlg_OnCommand(HWND hWnd, int id, HWND hWndCtl, UNIT codeNotify){    switch (id) {    case IDCCANCEL:        EndDialog(hWnd, id);//关闭对话框        break;    case IDC_BTN_STOP://一个button    {        DWORD dwThreadID:        CloseHandle(chBEGINTHREADEX(NULL, 0, StoppingThread,            NULL, 0, &dwThreadID))//开启 关闭线程        Button_Enable(hWndCtl, FALSE);//禁用stop键        }    break;    }}

初始化对话框

BOOL Dlg_OnInitDialog(HWND hWnd, HWND hWndFocus, LPARAM lParam){    chSETDLGICONS(hWnd, IDI_QUEUE);    g_hWnd = hWnd;    InitalizeSRWLock(&g_srwLock);//分配一个SRWLOCK结构并初始化    InitializeConditionVariable(&g_cvReadyToConsume)    InitializeConditionVariable(&g_cvReadyToProduce)    g_fShutdown = FALSE; //变量名取f时往往为1时起关闭作用    DWORD dwThreadID;    for (int x = 0; x < 4; x++)        g_hThreads[g_nNumThreads++] =             chBEGINTHREADEX(NULL, 0, WriterThread, (PVOID)(INT_PTR) x, 0, &dwThreadID);    for (int x = 0; x < 2; x++)        g_hThreads[g_nNumThreads++] =            chBEGINTHREADEX(NULL, 0, ReaderThread, (PVOID)(INT_PTR) x, 0, &dwThreadID);    return (TRUE);}

SRWLock

SRWLock对一个资源进行保护,不让其他线程访问它,并且允许我们区分读取者线程和写入者线程,所有的读取者线程访问共享资源是可行的,但是当写入者线程对资源进行更新时,写入者线程独占对资源的访问权

条件变量

来自msdn文档
Condition variables are synchronization primitives that enable threads to wait until a particular condition occurs. Condition variables are user-mode objects that cannot be shared across processes.
Condition variables enable threads to atomically release a lock and enter the sleeping state. They can be used with critical sections or slim reader/writer (SRW) locks. Condition variables support operations that “wake one” or “wake all” waiting threads. After a thread is woken, it re-acquires the lock it released when the thread entered the sleeping state.

写入者线程

DWORD WINAPI WriterThread(PVOID pvParam0) {    int nThreadNum = PtrToUlong(pvParam);    HWND hWndLB = GetDlgItem(g_hWnd, IDC_CLIENTS);    for (int nRequestNum = 1; ! g_fShutdown; nRequestNum++) {        CQueue::ELEMENT e = { nThreadNum, nRequest };        AcquireSRWLockExclusive(&g_srwLock);        if (g_q.IsFull() & !g_fShutdown){            AddText(hWndLB, TEXT("[%d] Queue is full: impossible to add %d"),nThreadNum, nRequestNum)//          需要等待读取者读取书据            SleepConditionVariableSRW(&g_cvReadyToProduce, &g_srwLock   ,INFINITE, 0);        }           if (g_fShutdown) {            AddText(hWndLB, TEXT("[%d] bye bye"), nThreadNum, nRequestNum);            ReleaseSRWLockExclusive(&g_srwLock);            WakeAllConditionVariable(&g_cvReadyToProduce);            return (0);        } else {//          当非满时独占资源写入数据            g_q.AddElement(e);            AddText(hWndLB, TEXT("[%d] Adding %d"), nThreadNum, nRequestNum);            ReleaseSRWLockExclusive(&g_srwLock);            WakeAllConditionVariable(&g_cvReadyToConsume);//          通知读取者线程            Sleep(1500);        }    }    AddText(hWndLB, TEXT("[%d] bye bye"), nThread, nThreadNum);}

读取者线程

DWORD WINAPI ReadThread(PVOID pvParam) {    int nThreadNum = PtrToUlong(pvParam);    HWND hWndLB = GetDlgItem(g_hWnd, IDC_SERVERS);    for (int nRequestNum = 1; ! g_fShutdown; nRequestNum++){        if (! ConsumeElement(nThreadNum, nRequestNum, hWndLB))            return (0);    Sleep(2500);    }}BOOL ConsumeElement(int nThreadNum, int nRequestNum, HWND hWndLB) {    AcquireSRWLockShared(&g_srwLock);    while (g_q.IsEmpty(nThreadNum) && !g_fShutdown) {        AddText(hWndLB, TEXT("[%d] Nothing to process"), nThreadNum);        SleepConditionVariableSRW(&g_cvReadyToConsume, &g_srwLock,            INFINITE, CONDITION_VARIABLE_LOCKMODE_SHARED);    }    if (g_fShutdown) {        AddText(hWndLB, Text("[%d] bye bye"), nThreadNum);        ReleaseSRWLockShared(&g_srwLock);        WakeConditionVariable(&_cvReadyToConsume);        return (FALSE);    }    CQueue::ELEMENT e;    g_q.GetNewElement(hThreadNum, e);    ReleaseSRWLockShared(&g_srwLock);    AddText(hWndLB, TEXT("[%d] Processing %d:%d"),        nThreadNum, e.m_nThreadNum, e.m_nRequestNum);    WakeConditionVariable(&g_cvReadyToProduce);//  通知写入者线程    return (TRUE);}

函数参数中含有…

这是类似与printf函数的定义,记住用法就好

void AddText(HWND hWndLB,PCTSTR pszFormat,...) {    va_list argList;    va_start(argList, pszFormat);    TCHAR sz[20 * 1024];    _vstprintf_s(sz, _countof(sz), pszFormat, argLIst);    ListBox_setCurSel(hWndLB, ListBox_AddString(hWndLB, sz));    va_end(argList);}

结束进程

void StopProcessing() {    if ( ! g_fShutdown) {        InterLockedExchange(&g_fShutdown, TRUE);        WakeAllConditionVariable(&g_cvReadyToProduce);        WakeAllConditionVariable(&g_cvReadyToConsume);        //  使所有的线程获取访问权        while (g_nNumThreads--){            CloseHandle(g_hThreads[g_nNumThreads]);        }        AddText(GetDlgItem(g_hWnd, IDC_SERVERS), TEXT("-----------------------"));        AddText(GetDlgItem(g_hWnd, IDC_CLIENTS), TEXT("-----------------------"));    }}
0 0
原创粉丝点击