      

     10 

     ,     ,   
  .     , 
  Win32,     .  
      :  , 
-, ,    .    
,        . 
             
 .        , 
      ,       
       . 
      ,    ,  
.  ,      
  ,        
.      , - 
     .      
 . 

         

            :  ,  
 ,  _ ,  
 .    ,   ,   
  ,    .   
  ,        
 ,     .  ,  
     . 
        ,       ,  
      ,  . 

    ,    

         ,      
  ,      
  ,  ,       . 
        , 
    . 
       ,       - 
   ,    ,  
 .   ?  : 

    218 ______________________________Windows   


    BOOL g_fFinishedCalculation = FALSE; 
    int WINAPI WinMainC...) { 
    CreateThread(..., RecalcFunc, ...); 
    
    //    
    while (!g_fFinishedCalculation) 
    
    DWORD WINAPI RecalcFunc(LPVOID IpvThreadParam) { 
    //   
    g_fFinishedCalculation = TRUE; 
    return(O); 
    } 

     ,   (   WinMain)  
   ,    RecalcFunc,   
  .   -     
   ,  -  . 
     ,     ,  ,   
 g_fFimshedCalculation     TRUE  , 
      ,   ,  
RecalcFunc.          
 RecalcFunc,      ,   
TRUE  g_fFinishedCalculation. 
       :   ,    
,           - . 
      
      (critical section)     , 
    -  .   
    ,     
     .    ,  
        . 
  : 
    int g_nlndex = 0; 
    const int MAX_TIMES = 1000; 
    DWORD g_dwTimes[MAX_TIMES]; 
    DWORD WINAPI FirstThread(LPVOID IpvThreadParm) { 
    BOOL fDone = FALSE; 

    __________________________ 10.   219 


    while (!fDone) { 
    if (g_nlndex >= MAX_TIMES) { 
    fDone = TRUE; 
    } else { 
    g_dwTimes[g_nIndex] = GetTickCountO; 
    g_nlndex++; 
    i 
    return(O); 
    } 
    DWORD WINAPI SecondThread(LPVOID IpvThreadParni) { 
    BOOL fDone = FALSE; 
    while (!fDone) { 
    if (g_nlndex >= MAX_TIMES) { 
    fDone = TRUE; 
    } else { 
    g_nlndex++; 
    g_dwTimes[g_nIndex - 1] = GetTickCountO; 
    } 
    return(O); 
    } 

     ,       , 
      .     
 FirstThread,     g_dwTimes    
 .      SecondThread     
  .         
    -      .   
   :  g_dw Times   ,  , 
            
 .     . 
    ,            
.      , . . SecondThread ( 
 ),       g_nlndexp,o 1,  
        FirstThread.    
g_dwTimes[l]   ,      
  . SecondThread    
g_dwTimes[l - 1]    .    
 ,  , , ,    
 g_dwTimes[l]  FirstThread.  ,   
       .  , 
    . 
    ,   , ,   , 
    .  :    
,     .      
    .       
,          , 
        .   
  ,         
.  ,   ,     
    . 

    220 ________________________________Windows   


     

             
CRITICAL_SECTION.    ,      
 .        
.   CRITICAL_SECTION       
WINNT.H',     . Win32-^yHKU,HH,  
 ,       
.      . 
         ,   -  
 : 

    int g_nlndex = 0; 
    const int MAX_TIMES = 1000; 
    DWORD g__dwTimes[MAX_TIMES]; 
    CRITICAL_SECTION g_Critical3ection: 
    
    int WINAPI WinMain(...) { 
    HANDLE hThreads[2]; 
    
    //      , 
    //     ,     
    InitializeCriticalSection(&g_CriticalSection); 
    hThreads[0] = CreateThread(..., FirstThread, ...); 
    nThreads[1] = CreateThread(..., SecondThread,    ) 
    // ,    ; 
    
    //       
    WaitForMultipleOb]ects(2, hThreads, TRUE, INFINITE); 
    
    //    
    CloseHandle(hThreads[0]); 
    CloseHandie(hThreads[1]); 
    
    //    
    DeleteCriticalSection(&g_CriticalSection); 
    } 
    DWORD WINAPI FirstThread(LPVOID IpvThread Farm) { BOOL fDone = FALSE; 
    while (!fDone) { 
    EnterCriticalSection(&g_CriticalSection); 
    if (g_nlndex >= MAX_TIMES) { 
    fDone = TRUE: 
    } else { 
    g_dwTimes[g_nIndex] = GetTickGount(); 
    g_nlndex++: 

    1.   CRITICAL_SECTION    RTL_CRITICAL_SECTION  
   WINBASE.H,    WINNT.H    RTL_CRITICAL_SECTION. 

    __________________________ 10.   221 



    LeaveCriticalSection(&g_CriticalSection); 
    } 
    return(O); 
    } 
    
    DWORD WINAPI SecondThread(LPVOID IpvThreadParm) { 
    BOOL fDone = FALSE: 
    
    while (!fDone) { 
    EnterCriticalSection(&g_CriticalSection); 
    
    if (g_nlndex >= MAX_TIMES) { 
    fDone = TRUE; 
    } else { 
    g_nlndex++; 
    g_dwTlmes[g_nIndex - 1] = GetTickCount(); 
    
    } 
    LeaveCriticalSection(&g_CriticalSection); 
    }  " 
    return(O); 


     

           ,  
   InitializeCriticalSection,    
CRITICAL_SECTION   IpCriticalSection: 

    VOID InitializeCriticalSection(LPCRITICAL_SECTION IpCriticalSection); 

           
EnterCriticalSection.       , 
  WinMain.     ,  
- g_CriticalSection    
InitializeCriticalSection  ,     . 
    , SecondThread  .   
EnterCriticalSection,    - g_CriticalSection: 

    VOID Enter-Cr-iticalSection(LPCRITICAL_SECTION IpCriticalSection): 

    ,    g_Critica1Section   ,  
          
 g_nlndex++. ,       
,     FirstThread.   
EnterCriticalSection,      ,   SecondThread. 
   EnterCriticalSection ,  - 
g_CriticalSection  ,     
.      ,  
        ,  
 . 
          ,  SecondThread 
 : 

    g_dwTimes[g_n!ndex - 1] = GetTickCount(); 

        g_dwTimes[0]    
.   ,    ,    ?  
,    g_dwTimes[l]  ,   g_dwTimes[0].  
 ,       ,   
    , 

    222 _______________________________Windows   

       ,     .    
        : 

    LeaveCriticalSection(&g_CriticalSection); 

         g_CriticalSection  , 
            . 
 ,   ,  ,  
EnterCriticalSection,       g_Critica1Section.  
EnterCriticalSection  , FirstThread  . 
     ,      
     -  .    
         
  .        
EnterCriticalSection.       ,  
     .     
,  LeaveCriticalSection,     
,      .      
  . 
     :          
     .   ,  
  EnterCriticalSection  ,   , 
     (reference count).    
    , ,     
,     LeaveCriticalSection,    
  . ,    : 

    int g_nNums[100]; 
    CRITICAL_SECTION g_CriticalSection: 
    
    DWORD WINAPI ThreadCLPVOID IpvParam) { 
    int nindex = (int) IpvParam: 
    
    EnterCriticalSection(&g_CriticalSection): 
    if (g_nNums[nIndex] < MIN_VAL) 
    IncrementNuiii(nlndex); 
    else 
    g_nNums[nIndex] = MIN_VAL: 
    LeaveCriticalSection(&g_CriticalSection); 
    return(O); 
    } 
    void IncrementNum(int nindex) { 
    EnterCnticalSection(&g_CriticalSection); 
    g_nNums[nIndex]++: 
    LeaveCriticalSection(&g_CriticalSection); 
    } 

        Thread      
  .       
  g_nNums [nindex],        
   .      MIN_VAL, 
 IncrementNum. 
    IncrementNum   .  ,  ,   
  .      g_nNums,   

    _________________________ 10.   223 

        ,   EnterCriticalSection. 
 IncrementNum  ,    , 
EnterCriticalSection          
   .   IncrementNum    
 ,      EnterCriticalSec^^^   
     LeaveCriticalSection  , 
  Thread. 
           ,   
CRITICAL_SECTION     .     
   InitTalizeCriticalSection      
 CRITICAL_SECTION.       
EnterCriticalSection,     CRITICAL_SECTION  , 
     . :    
,      ,  
,  : 

    int g_nNums[100]; 
    char g_cChars[100]; 
    CRITICAL_SECTION g_CriticalSection; 
    
    DWORD WINAPI ThreadFunc(LPVOID IpvParam) { 
    int x; 
    EnterCriticalSection(&g_CriticalSection); 
    for (x = 0; x < 100; x++) { 
    g_nNums[x] = 0: 
    g_cChars[x] = 'X'; 
    \ 
    LeaveCrlticalSection(&g_CriticalSection): 
    return(O): 

             
g_nNums  g_cChars     .     
.             
   .  ,  ,  ThreadFunc  : 
    
    DWORD WINAPI ThreadFuncd-PVOID IpvParam) { 
    int x; 
    Eni-erCrlticalSRCtlon(&g_CriticalSect1o'i): 
    
    for (x = 0; x < 100; x++) 
    g_nNums[x] =0; 
    
    for (x = 0; x < 100; x++) 
    g_cChars[x] = 'X'; 
    LeaveCriticalSection(&g_Criticat Sect ion); 
    return(O); 


    224 ______________________________Windows   

          ,   
  g_nNums  ,      
 ,      ThreadFunc   
. ,  :       
.    ,    : 

    int g_nNurns[100]: 
    char g_cChars[100]; 
     CRITICAL_SECTION g_CriticalSectionForNums; 
    0 CRITICAL_SECTION g_CriticalSectionForChars: 
    
    DWORD WINAPI ThreadFunc(LPVOID IpvParam) { 
    int x; 
    
    EiterCritica1Sec+ion(&r5_Criti('alSectionForNunis): 
    
    for (x = 0; x < 100; x++) 
    g_nNums[x] = 0; 
    LeaveCriticalSection(&g_CriticalSectionForNums); 
    EnterCriticalSection(&g_CriticalSectionForChars): 
    
    for (x = 0; x < 100; x++) 
    g_cChars[x] = 'X'; 
    LeaveCr11:1ca1 Section(&g_Crit!calSection For Chars); 
    return(O); 
    } 

           g_nNums,   
ThreadFunc   . 
            .  
ThreadFunc   : 
    
    DWORD WINAPI ThreadFuncCLPVOID IpvParam) { 
    int x; 
    EnterCriticalSection(&g_CriticalSectionForNuins); 
    EnterCriticalSection(&g_CriticalSectionForChars); 
    
    for (x = 0; x < 100; x++) 
    g_nNums[x] = 0; 
    
    for (x = 0; x < 100; x++) 
    g_cChars[x] = 'X'; 
    
    LeaveCrlticalSection(&g_CriticalSectionForChars); 
    Lea veC r it ica 1 Sect 1 on (&g_Cr it leal Sect ion For Mums); 
    return(O); 
    } 

    ,           
;      : 

    ________________________ 10.   225 
    

    DWORD WINAP1 OnierFnreadPuncd-PVOlD IpvParani) { 
    int x: 
    EnterCritlcalSection(&g_CriticalSectionForClidi a); 
    EnterCriticalSection(&g_CriticalSectionForNu(iis); 
    
    for (x = 0: x < 100; x++) 
    g_nNums[x] = 0; 
    
    for (x = 0; x < 100: x++) 
    g_cChars[x] = 'X'; 
    LeaveCriticalSection(&g_CriticalSectionForNums); 
    LeaveCriticalSection(&g_CriticalSectionForChars); 
    return(O); 
    } 

         EnterCriticalSection  
beaveCriticalSection.  - ,   ThreadFunc  OtherThreadFunc 
  ,     (deadlock). 
 ,           
 (    )    . 
    , ThreadFunc       
g_CriticalSectionForNums.     ,   
 OtherThreadFunc    
g_CriticalSectionForChars. -     . 
     ThreadFunc  OtherThreadFunc     
,     ,    . 
          ,    
 ,    EnterCriticalSection   . 
          . 
       ,       
   . ,       
    g_nNums[3]   ,      
  WM_SOMEMSG: 

    int g_nNuiiis[100]; 
    CRITICAL_SECTION g_CriticalSection: 
    
    DWORD WINAP1 SomeThr-eadCLPVOID IpvParam) { 
    Ente rC r ill ca 1 Sect i  n(&g_C Fit-Leal Sect ion); 
    
    //    -  
    SendMessage(hwndSomeWnd, WM_SOMEMSG, g_nNums[3], 0); 
    LeaveCr-iticalSection(&g_CriticalSection); 
    return(O): 
    } 

     ,      WM_SOMEMSG  
  ,  ,  ,   2.  
           
g_nNums.     : 
    2.   -  ,    
,    ,      23 . 

    226 ______________________________Windows   

    int g_nNu(ns[100]; 
    CRITICAL_SECTION g_CriticalSection; 
    
    DWORD WINAPI SomeThread(LPVOID IpvParam) { 
    int nTemp: 
    
    EnterCriticalSection(&g_CriticalSection); 
    nTemp = g_nNums[3]; 
    LeaveCriticalSection(&g_CriticalSection); 
    
    //    -  
    SendMessage(hwndSomeWnd, WM_SOMEMSG, nTemp, ): 
    return(O); 

         g_nNums[3]    
nTemp  .  ,       
   .     
LeaveCriticalSection       .    
    ,    
   ,      
    . 
          CRITICAL_SECTION   
 DeleteCriticalSection: 

    VOID OeleteCriticalSection(LPCRITICAL_SECTION IpCrlticalSection); 

       ,    . , 
,  EnterCriticalSection  LeaveCriticalSection  
,     CRITICAL_SECTION,    
   InitializeCriticalSection.  ,  
      ,  -  
   EnterCriticalSection. 
     Windows NT 4   ,    : 

    BOOL TryEnterCriticalSection(LPCRITICAL_SECTION IpCriticalSection): 

       TryEnterCriticalSection     
  ,  ,      
      TRUE.    
  ,    FALSE.   
EnterCriticalSection  TryEnterCriticalSection  ,     
  . 
    VwiNDowsy  Windows 95 TryEnterCriticalSection  .  
   \95/   Windows 95,    . 

    - CritSecs 

     CritSecs (CRITSECS. EXE) (.   . 10-1) 
      .  
         CRITSECS  
-,   . 
       WinMain    , 
   .      
 WN_INITDIALOG,  Dlg_OnInitDialog   
 CRITICAL_SECTION       ,  
   : 
    Counter Thread  DisplayThread.       
  

    ________________________ 10.   227 

    :  ( ,       
 ), CounterThread  Display Thread. 
    -    CRITSECS.C  : 
    
    // ,   
    TCHAR g_szNumber[10] = __("0"); 

      ,  ,   0.  
CounterThread     ,  1 ,   
,     .  Display Thread   
   g_szNumber      ,   
 . 
      CritSecs,  ,    ,  
     Critical Section Test Application 
 : 

    III 1111111111 1111 11111111111111^^^^^^ 1 1 II 

    ,  ,        , 
           
g_szNumber.    ~ CounterThread     
,        ,  
DisplayThread    g_szNumber      . 
            Synchronize 
().      
g_CriticalSection,      g_szNumber.   
      : 

    228 ______________________________Windows   

            CritSecs. 
  Process Priority Class (  ). 
Display Thread Priority (  )  Counter Thread Priority 
( -)       
 CritSecs,       , 
  CounterThread  Display Thread. 
     Pause () ,    
   CounterThread  Display Thread  
 SuspendThread  ResumeThread. 
     Show Counter Thread ( -)  
CounterThread         : 

    Cntr: Increment 

          : 
         DisplayThread  ,   
CounterThread.  DisplayThread      CounterThread 
     .    ,  
       
   .     
,         . 
     CritSecs        
     : 
         (    Windows NT); 
       ; 
      ,  ,   ; 
        ; 
       ,    . 
            CritSecs. -, 
CounterThread,      g_szNumber,  
\32- Sleep.   : 

    VOID SIeep(DWORD cMilliseconds); 

       Sleep,   ,    
-  (  cMilliseconds)   
  .  

    __________________________ 10.   229 

      Counter Thread    cMilliseconds , . . 
 ,    0      
.    ,        
Sleep   .    _   
    .    Sleep (0)  
CounterThread,    ,    
   CritSecs.    CritSecs     
  -    ,   
    . 
    -,      ,     
     .     
   CounterThread,  DisplayThread    : 

    fSyncChecked = IsDlgButtonChecked(g_hwnd, IDC_SYNCHRONIZE); 

            Synchronize  
   .      : 

    if (fSyncChecked) { 
    EnterCriticalSection(&g_CriticalSection): 
    } 
    if (fSyncChecked) { 
    LeaveCriticalSection(&g_CritlcalSection); 
    } 

         CritSecs,   : 

    if (Is01gButtonChecked(g_hwnd, IDC_SYNCHRONIZE)) { 
    EnterCriticalSection(&g_CritlcalSection); 
    i 
    
    if (IsDlgButtonChecked(g_hwnd, IDC_SYNCHRONIZE)) { 
    LeaveGriticalSection(&g_CriticalSection); 
    } 

          , -  - 
   .    ?    CounterThread 
,   ,    EnterCriticalSection.  
DisplayThread, ,   ,   EnterCriticalSection. 
       EnterCriticalSection    
 ,        .   
.  CounterThread  ,     Synchronize. 
  CounterThread,     IsDIgButtonChecked,    
LeaveCriticalSection.  ,    , 
CounterThread    ,  ,   
DisplayThread,   ,       . 
    ,          
   EnterCriticalSection  I^eaveCriticalSection,  
     .  ,  
,        . 

    230 _______________________________Windows   


    CRITSECS.C 
    
    : CritSecs.C 
    : Copyright  1995-1997,   (Jeffrey Richter) 
    
    ^include "..\CmnHdr.H"           /* .   */ 
    ^include <windows.h> 
    #include <windowsx.h> 
    ftinclude <tchar.h> 
    #include <stdio.h>               //  sprintf 
    #include <process,h>             //  _beginthreadex 
    ffinclude "Resource.H" 
    ////////////////////////''////////////////''/////////''////'/''//'//',1 
,''   
    //  . 
    // g_fTerminate  TRUE    . 
    //       . 
    //    volatile,     
    //    . 
    volatile BOOL g_fTerminate = FALSE; 
    HWND  g_hwnd; 
    HANDLE g_hThread[2]; //  Counter[0]  Display[1] 
    
    // ,   
    TCHAR g_szNumber[10] = __TEXT("0"); 
    
    //      
    CRITICAL_SECTION g_CnticalSection: 
    illllllllllllllllllllllll/IHII/IIIIIIIIIIIHIIHIIIIIIIilllllllll/llllllllllll 
    
    / I      
    void AddToListBox (LPCTSTR szBuffer) { 
    HWND hwndDataBox = GetDlgItem(g_hwnd, IDC_OATABOX): 
    int x = ListBox_AddString(hwndDataBox, szBuffer); 
    ListBox_SetCurSel(hwndDataBox, x); 
    if (ListBox_GetCount(hwndDataBox) > 100) 
    ListBox_DeleteStnng( hwndDataBox, 0); 
    i 
    /////////////////////////////////////////////////////////////////////////////// 
    
    II ,       
    DWORD WINAPI Counter-Thread (LPVOID IpThreadParameter) { 
    unsigned int nNumber, nDigit; 
    BOOL fSyncChecked; 
    . . . 

    . 10-1.   CritSecs 


    __________________________ 10.   231 


    . 10-1 () 

    while (!g_fTerminate) { 
    
    //    Synchronize    
    fSyncChecked = IsDlgButtonChecked(g_hwnd, IDC_SYNCHRONIZE); 
    if (fSyncChecked) { 
    
    //     ,   
    EnterCriticalSection(&g_CritlcalSection); 
    
    //          1 
    _stscanf(g_szNuiiiber, __TEXT("%d"), &nNumber); 
    nNumber++: 
    
    //      
    nDigit = 0; 
    while (nNumber != 0) { 
    //      
    g_szNumber[nDigit++] = (TCHAR) (__('0') + (nNumber % 10)); 
    //    Sleep  ,   
    //        . 
    //        ,  
    //        
    // .   Sleep  , ,  . 
    Sleep(O); 
    
    //     
    nNumber /= 10; 
    } 
    
    //     ;   
    g_szNuinber[nDigit] = 0. 
    
    II     ;  
    //  .  ANSI,  _strrev,   
    // Unicode,  - _wcsrev. 
    _tcsrev(g_szNumber); 
    if (fSyncChecked) { 
    //     ,  . 
    //         
    // l3DlgButtonChecked  ,    
    // fSyncChecked.    ,    
    // Synchronize         
    //   EnterCriticalSection  LeaveCriticalSection. 
    //        ,  
    //    ,      
    //    . 
    LeaveCriticalSection(&g_CriticalSection); 

    . ^. . 

    232 ________________:_____________Windows   


    . 10-1 () 
    
    //   ] - 1   ; 
    //  ,   
    if (IsDlgButtonChecked(g_hwnd, IDC_SHOWCNTRTHRD)) 
    AddToListBox(__TEXT("Cntr: Increment")); 
    return(O); //       
    } 
    ; ' ' / I I ! 1 / / 11 / / / I I / I I ! 11 I I i I I I I I / I I I / I I 
/ 1 ! / ! ! I I I ! I / / ! /1 i I i ' // / / ' , '/ //11'/ !. ! '.'. 
    // ,      
    // ( )    
    DWORD WINAPI DisplayThread (LPVOIO IpThreadParameter) { 
    BOOL fSyncChecked; 
    TCHAR szBuffer[50]: 
    while (!g_rTerminate) { 
    
    // :     
    fSyncGhecked = IsDlgButtonChecked(g_hwnd, IDC_SYNCHRONIZE); 
    if (fSyncGhecked) 
    EnterCriticalSection(&g_CriticalSection); 
    
    //       
    _stprintf(szBuffer, __TEXT("Dspy: %s"), g_szNumber); 
    if (fSyncChecked) 
    LeaveCriticalSection(&g_CriticalSection); 
    //      
    AddToListBox(szBuffer); 
    } 
    return(O): //       
    
    BOOL Dlg_OnInitDialog (HWND hwnd, HWND hwndFocus, LPARAM IParam) { 
    HWND hWndCtI; 
    DWORD dwThreadID; 
    
    //      
    chSETOLGICONS(hwnd. IDI_CRITSECS, IDI_CRITSECS); 
    
    //       , 
    //        .   
    //    . 
    g_hwnd = hwnd: 

    . 1>. . 

    278 _______________________________Windows   

    //    ,   ; 
    
    //      ,    
    // -"",    
    HANDLE hSernNumReaders: 
    } SWMRG, *PSWMRG; 

            . 
 , hMutexNoWriter,  SWMRG-,  
,       -. 
: ,   -   ,   
 ,     . -  
     ,       
.   , , -     . 
     , hEventNoReaders,  ,     
   -.        
,      . 
     , hSernNumReaders,    
-,       . 
SWMRG-           
.  SWMRG    ,     
  ,   ;      
 SWMRGDoneReading,  ,  ,  SetEvent,  
  ,   hEven tNoR coders. 
      SWMRG,       
    LONG.      ,  
 .      SWMRG     
    .    : , 
       SWMRGInitialize   
     ?    
,        1      
 -     4- .  ,  
   4096 ,   102 400%,     
  8192  (DEC Alpha)   204 800%!  . 
      .      ,    
:    ,        
 .           
 .   ,   WaitForSingleObject  
   ,       
ReleaseSemaphore. ,       
,  ,   ,  ,     0, 
 WaitForSingleObject      .   
 WAIT_TIMEOUT,   ,    WAIT_OBJECT_0,  
 0.  ,     ,   ,  
 SWMRG,     . 
       SWMRG.  ,   , , 
,      . 
     SWMRGInitialize   SWMRG.   , 
  .          
 SWMRG,        
.   SWMRGInitialize        
 SWMRG.        , 
  .  , ,  SWMRGInitialize,   
  IpszName  Jeff,   

     10.   279 

      SWMRGMutexNoWriterJeff,   SWMRGEventNoReadersJeff, a 
  SWMRGSemNumReadersJeff.    IpszNameB 
       
 ConstructObjName. 
          SWMRGInitialize   
    IpszName,  ,     
   ,       . 
       . 
    SWMRGDelete   .      
CloseHandle (     ). 
     -      , 
      ,  SWMRGWaitToWrite.  
  32- WaitForMultipleObjects,     
:  (hMutexNoWriter)   (hEventNoR eaders).  
WaitForMultipleObjects  WAIT_OBJECT_0, ,    
   ( ,  ).    
 WAIT_TIMEOUT, - ,    
  ,       -  
  -. 
       , -  
SWMRGDoneWriting.   (hMutexNoWriter),     
 ,        . 
     -       ,  
     ,  SWMRGWaitToRead.  
  Win32 WaitForSingleObject,     
(hMutexNoWriter).   - ,  -   
   ,       -.  
      WaitForSingleObject , 
SWMRGWaitToRead  WAIT_TIMEOUT. 
    ,   WaitForSingleObject    
-,   (  -) 
 .    Releases emaphore    
 hSemNumReaders   cReleaseCount,  1.  
        DWORD, 
     . SWMRGWaitToRead   
 ,    ReleaseSemaphore     
   -,     
(hEventNoReaders), ,         
-.        ,    
,     ResetEvent. 
        SWMRGWaitToRead  ReleaseMutex, 
   hMutexNoWriter. ?   ,   
SWMRGWaitToRead    -,  ( 
 )     .    ,   
     -. ,  
     ,  ReleaseMutex, 
      . 
      ,    ,  SWMRGDoneReading.  
  -,     .   
   WaitForMultipleObjects,    
hMutexNoWriter,   ,  SWMRGDoneReading,   
    hEventNoReaders  hSemNumReaders.   
   ,       
 ,  ,  ,    . 
   (SWMRGWaitToWrite, SWMRGDoneWriting, SWMRGWaitToRead  
SWMRGDoneReading),    ,     

    _________________________ 10.    233 

    . 10-1 () 

    I/   .    
    //  ,      - . 
    InitializeCriticalSection(&g_CriticalSection); 
    
    //     Counter-Thread    
    g_hThread[0] = chBEGINTHREADEX(NULL. , Counter-Thread, NULL, 0, &dwThreadID); 
    
    //     DisplayThread    
    g_hThread[1] = chBEGINTHREADEX(NULL, 0, DisplayThread, NULL, 0, &dwThreadID): 
    //    Process Priority Class 
    //   Normal 
    hWndCtI = GetDlgItem(hwnd, IDC_PRIORITYCLASS); 
    ComboBox_AddString(hWndCtl, __TEXT("Idle")); 
    ComboBox_AddString(hWndCtl, __TEXT("Normal")): 
    ComboBox_AddString(hWndCtl, __TEXT("High")); 
    ComboBox_AddString(hWhdCtl, __TEXT("Realtime")); 
    ComboBox_SetCurSel(hWndCtl, 1); // Normal 
    //    Display Thread Priority 
    //   Normal 
    hWndCtI = GetDlgItem(hwnd, IDC^DSPYTHRDPRIORITY): 
    ComboBox_AddString(hWndCtl, __TEXT("Idle")); 
    ComboBox_AddString(hWndCtl, __TEXT("Lowest")): 
    ComboBox_AddString(hWndCtl, __TEXT("Below normal")): 
    Combo8ox_AddString(hWndCtl, _J"EXT("Normal")); 
    ComboBox_AddString(hWndCtl. __TEXT("Above normal")): 
    ComboBox_AddString(hWndCtl, __TEXT("Highest")); 
    ComboBox_AddString(hWndCtl, __TEXT("Timecritical")); 
    ComboBox_SetCurSel(hWndCtl, 3); // Normal 
    //    Counter Thread Priority 
    //   Normal 
    hWhdCt! = GetDlgItem(hwnd, IDC_CNTRTHRDPRIORITY): 
    ComboBox_AddSt ring(hWhdGtl, __TEXT("Idle")): 
    ComboBox_AddString(hWhdCtl, __TEXT("Lowest")); 
    ComboBox_AddString(hWndCtl, __TEXT("Below normal")); 
    ComboBox_AddStnng(hWndCtl, __TEXT( "Normal")): 
    ComboBox_AddString(hWhdCtl, __TEXT("Above normal")); 
    ComboBox_AddString(hWndCtl, __TEXT("Highest")); 
    ComboBox_AddString(hWndCtl, __TEXT("Timecritical")); 
    ComboBox_SetCurSel(hWndCtl, 3); // Normal 
    return(TRUE); 
    } 
    lilllllllllll!illlll///ll/ll/tllll//l/llillll///lll/lll//llllllllllllllllllllll 

    . . . 

    234 ____________________________Windows   

    . 10-1 () 

    void Dlg_OnDestroy (HWND hwnd) { 
    
    //    ,  , 
    //     
    c]._fTerminate = TRUE: 
    
    //   ,    
    ResumeThread(g_hThread[0]); 
    ResumeThread(g_hThread[1]); 
    ^ 
    void Dlg_OnGommand (HWND hwnd, int id, HWND hwndCti, UINT codeNotity) { 
    HANDLE hThread; 
    DWORD dw; 
    
    switch (id) { 
    case IDCANCEL: 
    EndDiaiog(hwnd, id); 
    break; 
    case IDC_PRIORITYCLASS: 
    
    if (codeNotify != CBN_SELCHANGE) 
    break: 
    
    //     
    switch (ComboBox_GetCurSel(hwndCtl)) { 
    case 0: 
    dw = IDLE_PRIORITY_CLASS; 
    break; 
    case 1: 
    default; 
    dw = NORMAL_PRIORITY_CLASS; 
    break; 
    case 2: 
    dw = HIGH_PRIORITY_CLASS; 
    break; 
    case 3: 
    dw = REALTIME_PRIORITY_GLASS: 
    break; 
    ) 
    SetPriorityClass(GetCurrentProcess(), dw); 
    break; 

    . . . 

    __________________________ 10.   235 


    . 10-1 () 


    case IDC_DSPYTHRDPRIORITY: 
    case IDC_CNTRTHROPRIORITY: 
    
    if (codeNotify != CBN_SELCHANGE) 
    break; 
    
    switch (ComboBox_GetCurSel(hwndCtl)) { 
    case 0: 
    dw = (DWORD) THREAD_PRIORITY_IDLE; 
    break; 
    case 1: 
    dw = (DWORD) THREAD_PRIORITY_LOWEST: 
    break; 
    case 2: 
    dw = (DWORD) THREAD_PRIORITY_BELOW_NORMAL; 
    break: 
    case 3: 
    default: 
    dw = (DWORD) THREAD_PRIORITY_NORMAL: 
    break; 
    case 4: 
    dw = (DWORD) THREAD_PRIORITY_ABOVE_NORMAL; 
    break; 
    case 5: 
    dw = (DWORD) THREAD_PRIORITY_HIGHEST; 
    break; 
    case 6: 
    dw = (DWORD) THREAD_PRIORITY_TIME_CRITICAE; 
    break; 
    } 
    //     
    //    
    hThread = (id == IDC_CNTRTHRDPRIORITY) ? g_hThread[0] : g_hThread[1]; 
    SetThreadPriority(hThread. dw): 
    break; 
    case IDC_PAUSE: 
    
    //    
    //    

    . . . 

    236 ______________________________Windows   


    . 10-1 () 

    it (Button_GetCheck(hwnaCtl)) { 
    SuspendThread(g_hThread[0]); 
    SuspendThread(g_hThread[1]); 
    } else { 
    ResumeThread(g_hThread[0]): 
    ResumeThread(g_hThread[1]); 
    } 
    break; 
    i 
    .'7/////////////////7////////////////////////////,'///////7////.-7//,/.1,/.,,1'1',/.11,1, 
    BOOL CALLBACK Dlg_Proc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM 
IParam) { 
    switch (uMsg) { 
    chHANDLE_DLGMSG(hwnd, WM_INITDIALOG, Dlg_0nlnit0ialog); 
    chHANDLE_DLGMSG(hwnd, WM_DESTROY, Dlg_0n0estroy); 
    chHANDLEDLGMSG(hwnd, WM_COMMAND, Dlg_OnCommand); 
    } 
    return(FALSE): 
    Illllllllllllllll/llll/llllllll/llllllllllllllllllllllllltlllllllltllllllltllll 
    int WINAPI _tWinMain (HINSTANCE hinstExe, 
    HINSTANCE hinstPrev, LPTSTR pszCmdLine, int nCmdShow) { 
    ChWARNIFUNICODEUNDERWIN95(); 
    DialogBox(hinstExe, MAKEINTRESOURCE(IDO_CRITSECS), NULL, Dlg_Proc); 
    
    //     
    WaitForMultipleObjects(2, g_hThread, TRUE, INFINITE); 
    
    //    
    CloseHandle(g_hThread[0]); 
    CloseHandle(g_hThread[1]); 
    
    //       , 
    //     
    DeleteCriticalSection(&g_CriticalSection); 
    return(O); 
    IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII   ///////////////////////////////// 

    ___________________________ 10.   237 


         

       , , ,  ,  
    ,   
,   ,    . ,   
  ,  ,   ,  
          . 
           : 
     ; 
     ; 
     ; 
      ; 
      . ; 
     -; 
     ; 
      (    ); 
       (waitable timers) (  Windows NT 4  ). 
            :  
(signaled)   (nonsignaled).      
 - . , ,    
   ,        
  ,   .   3   
,          
 .      .   
     ,      
   .      
 . 
        -    
 .  ,      ( 
).   ( )     , 
   . 
            
 ,      ,    . 
,       ,   
 32-,        
 .         
  . 
              
  .       .  
 ,        -    
        -  
  /. (     15.) 
            .  
   ,        CreateFile. 
         
   ,         
      . 
    _  (   , , , 
   )  __   .  
Win32,       , 
  

    238 _______________________________Windows   

      ,       . 
        .   
  ,      , , 
   ;       
   14. 
     _   -     
  : 

    DWORD WaitForSingleObject(HANDLE hObject, DWORD dwTimeout); 

     

    DWORD WaitForMultipleObJects(DWORO cObjects, LPHANDLE IpHandles, BOOL 
bWaitAll, DWORD dwTimeout); 

    WaitForSingleObject  ,     
 ,     hObject.  dwTimeout 
,   ( )     
.           
 ,        
. WaitForSingleObject     : 

                     

    WAIT_OBJECT_0         000000000            . 
    WAIT_TIMEOUT         000000102             
    dwTimeout  . 
    WAIT_ABANDONED      000000080        -    
 -    (.      ). 
    WAIT_FAILED            OxFFFFFFFF         .    
,  GetLastError. 

      dwTimeout  WaitForSingleObject    
 .  ,     - ,   
 :    .    WAIT_OBJECT_0, 
 , WAIT_TIMEOUT  . , ,  INFINITE 
(OxFFFFFFFF)  WaitForSingleObject ,   .  
 ,      ,     
      . 
    WaitForMultipleObjects  WaitForSingleObject   , 
        - 
   .      cObjects  
    (  MAXIMUM_WAIT_OBJECTS, 
  64).  IpHandles    , 
  .       ,  
         . 
     bWaitAll ,       
    .    TRUE, WaitForMultipleObjects  
      .   FALSE  
     .     
   (   ),    
   .  dwTimeout  
   WaitForSingleObject.    
 , WaitForMultipleObjects     
,    . 

    _____________._____.._______ 10.   239 


    WaitForMultipleObjects     : 

                   

     WAIT_OBJECT_0                   
    (WAIT_OBJECT_0 +        000000000      ,   
 cdbjects - 1)                             .   
           
 IpHandles,   ,    . 
    WAIT_TIMEOUT         000000102            
     dwTimeout  . 
     WAIT_ABANDONED                 
     (WAIT_ABANDONED +  000000080      ,   
  
    cObjects - 1)                                   
,     -   .   
           
 IpHandles,   ,   
  -   . 
    WAIT_FAILED            OxFFFFFFFF      .    
,  GetLastError. 

     WaitForSingleObject  WaitForMultipleObjects   
      .     
    ,       
    .  :  10   
WaitForSingleObject  -       , 
           
    .        . 
      -,        
 (auto-reset waitable timers)  WaitForSingleObject  
WaitForMultipleObjects     .     
      ,   
  .         
      .    
 ,         
    . 
         WaitForMultipleObjects:     
 bWaitAll,  TRUE, ,  ,  
      ,     
 ,   .  ,    
  , ,    , WaitForMultipleObjects 
   -,    
  .  :      
        
 ,   . (   
WaitForMultipleObjects   ,     
    .      , 
       -    
  .) 
     ,  ,     . ,  1 
  :     .  ,   2  
  - 

    240 _______________________________Windows   

         ,      1.  
   ,   1       
    .    2  
WaitForSingleObject,       .  
?        .  
  1       ,    , 
     2. 
      WaitForMultipleObjects       
 .           
,    ,     . 
,  1  2     
WaitForMultipleObjects   -   .     
 (,    ).  ,   
    1.          . 
      2.  - ,   1  
2, - , ,  ,      , 
 . 
     ,   ?  1  - ,   
  ,       . 
,  2          
 . ,    , 
WaitForMultipleObjects       ,   
 (  )   . 

    - 

              ,  
     ^      
.   -      
   CreateMutex: 

    HANDLE CreateMutex(LPSECURITY_ATTRIBUTES Ipsa, BOOL fInitialOwner, 
    LPTSTR IpszMutexName); 

     Ipsa    SECURITY_ATTRIBUTES.  
fInitialOwner ,   ,  ,  
   .    TRUE,   
  , , , -   
 .   ,   ,  
,  ,   ,   .  
FALSE   fInitialOwner ,  -  
        .   
             
 . 
     IpszMutexName   NULL,    (  
  ),  .    
CreateMutex,         ,  
   IpszMutexName.      
     (     ). 
CreateMutex  - ,   -. 
        -     , 
    ,    .  
        ,   
    -.   
   .  :    
   CreateMutex,       
IpszMutexName  .       
  ,      
   ,      . 
    ,   CreateMutex   -, 
  GetLastError (        
CreateMutex).  GetLastError 

    ________________________ 10.   241 

     ERROR_ALREADY_EXISTS, ,  -  .  
         ,   
   . 
            OpenMutex: 

    HANDLE OpenMuTex"( DWORD fdwAccess. BOOL finherit, LPTSTR IpszName); 

     fdwAccess     SYNCHRONIZE,  
MUTEX_ALL_ACCESS.  finherit ,     
   -.   IpszName    
-        . 
      OpenMutex    -, 
,       ,    IpszName. 
 ,    ,    
,     .      
         , 
  .       , 
  NUEL. 
        ,   -  - 
.     ,      .   
    DuplicateHandk,     
 .      2. 

         

      ,     
,  -.     ,  
 ,      : 

    int g_nlndex = 0; 
    const int MAX_TIMES = 1000: 
    DWORD g_dwTimes[MAX_TIMES]: 
    HANDLE g_hMutex = NULL: 
    int WINAPI WinMain(... ) { 
    HANDLE hThreads[2]; 
    //     , 4iu6oi    iuru, 
    //     
    g_hMutex = CreateMutex(NULL, FALSE, NULL); 
    
    //      
    hThreads[0] = CreateThread(..., FirstThread, ...): 
    hThreads[1] = CreateThread(..,, SecondThread, ...): 
    
    // .     
    WaitForMultipleObjects(2, hThreads, TRUE, INFINITE); 
    
    //    
    CloseHandle(hThreads[0]); 
    CloseHandle(hThreads[1]); 
    
    //   
    CloseHandle(g_hMutex); 
    } 

    . . . 


    242 _______________________________Windows   
    

    DWORD WINAPI FirstThread(LPVOID IpvThreadParm) { 
    BOOL fDone = FALSE: 
    DWORD dw; 
    while (!fDone) { 
    
    //  ,    
    dw = WaitForSingleOb]ect(g_hMutex, INFINITE); 
    if (dw == WAIT_OBJECT_0) { 
    
    //      
    if (g_nlndex >= MAX_TIMES) { 
    fDone = TRUE; 
    } else { 
    g_dwTimes[g_nIndex] = GetTickCount(); 
    g_nlndex++; 
    } 
    
    //   
    ReleaseMutex(g_hMutex); 
    } else { 
    
    //    - 
    break: //    while 
    } 
    return(O); 
    
    DWORD WINAPI SecondThread(LPVOID IpvThreadParm) { 
    BOOL fDone = FALSE: 
    DWORD dw; 
    while (!fDone) { 
    
    //  ,    
    dw = WaitForSingleObject(g_hMutex, INFINITE); 
    if (dw == WAIT_OBJECT_0) { 
    
    //      
    if (g_nlndex >= MAX_TIMES) { 
    fDone = TRUE; 
    } else { 
    g_nlndex++; 
    g_dwTimes[g_nIndex - 1] = GetTickCount(); 
    \ 
    //   
    ReleaseMutex(g_hMutex); 
    } else { 
    
    //    - 
    break; //    while 
    } 
    } 
    return(O); 


    ___________________________ 10.   243 

         ,     -   
.   ,     WaitForSingleObject,  
   NULL (-  ).      
-;       : 
    
    //   ,      
    hThreads[0] = CreateTnread(..., FirstThread, NULL, CREATE_SUSPENDED, ...); 
    hThreads[1] = CreateThreadC..., SecondThread, NULL, CREATE_SUSPENDED, ...); 
    
    //   
    g_hMutex = CreateMutex(NULL, FALSE, NULL); 
    
    //    
    ResLimeThread(hThreads[0]); 
    ResumeTnread(nTnreads[1]); 

        ,     .    
 ,    .    
-        g_hMutex. 
   ,      NULL,    
 ,   ResumeThread.     
:      ,       . 
        WinMain   .    
,         , 
    ^" WaitForMultipleObjects.     
      2,   ,   
    ;  hThreads   
 , a TRUE ,      
  , . .   .   
INFINITE ,         
  .     WaitForMultipleObjects 
 WinMain  CloseHandle,   -. 
            
  -.  EnterCriticalSection   
  WaitForSingleObject.        
: WAIT_OBJECT_0, WAIT_ABANDONED  WAIT_TIMEOUT.  WAIT_TIMEOUT  
   ,       
 INFINITE.   WAIT_OBJECT_0 ,  
-       .  
WaitForSingleObject ,  -    
,     ,      
 .          
,   ReleaseMutex: 

    BOOL ReleaseMutex(HANDLE hMutex): 

       -     , . 
.    ,   LeaveCriticalSection    
 .      : ReleaseMutex 
  ,   ,  ,   
.     ReleaseMutex  ,  
-,       . ,  
  ,      .  
     ,     ,  
 ,   

    244 ______________________________Windows   

        .   ,   
 ,             . 
      :         
 ,        
- .       ,   
     . 

      - 

    -       , 
        .  
     ,     .  
-    ,    . 
  - ,      
  (   ),   .   
 ,       ,  
        ReleaseMutex. 
          , ,  , 
     .  , 
    WaitForSingleObject,   
 ,     WAIT_ABANDONED  
WAIT_OBJECT_0.  ,  ,    
.     ,       
. ,         
 -, , . (  :   
   ExitThread  Term in ate Thread.) 
           ,      
, ,   ,   while,    . 
,  WinMain ,    ,   
-   .      
  WaitForSingleObject  WAIT_ABANDONED,   
       . 
     .  -  , , 
       - . , 
   WaitForSingleObject     
-,           
(          ,    
  -).  ,    
WaitForSingleObject    -   
  1.  ,      , 
      ReleaseMutex.  
EnterCriticalSection  LeaveCriticalSection     
   . 

    - Mutexes 

     Mutexes (MUTEXES. EXE) (.   . 10-2)  
    CritSecs,    
-.     Mutexes     
,   CritSecs.    -  
       CounterThread   , 
a DisplayThread    (       ).  
       MUTEXES  , 
  . 
  . 


    _________________________ 10.   245 


    MUTEXES.C 
    
    : Mutexes.C 
    : Copyright  1995-1997,   (Jeffrey Richter) 
    ftinclude "..\CmnHdr,H"           /* .   */ 
    #include <windows,h> 
    #include <windowsx.h> 
    #include <tchar.h> 
    ^include <stdio.h>               //  sprintf 
    ^include <process.h>             //  _beginthreadex 
    ftinclude "Resource.H" 
    Illlllllllllllllllllllllllll/lllllllllllllllllllllll/llll/l/lllllllllllllllllll 
    I/  . 
    // g_fTerminate  TRUE    . 
    //       . 
    //    volatile,     
    //    , 
    volatile BOOL g_fTerminate = FALSE: 
    HWND  g_hwnd; 
    HANDLE g_hThread[2]; //  Counter[0]  Oisplay[1] 
    
    // ,   
    TCHAR g_szNumber[10] = __TEXT("0"); 
    
    // ,     
    HANDLE g_hMutex; 
    IIIIIIIIIIIHIIIIIIIIIIIflllllll/llllllllllllllllllllllllllllllllllllllllllllll 
    
    I /      
    void AddToListBox (LPCTSTR szBuffer) < 
    HWND hwndDataBox = GetDlgItem(g_hwnd, IDC_OATABOX); 
    int x = ListBox_AddString(hwndDataBox, szBuffer); 
    ListBox_SetCurSel(hwndDataBox, x); 
    
    if (ListBox_GetCount(hwndDataBox) > 100) 
    ListBox_DeleteString(hwndDataBox, 0); 
    lllll/illllililll/lll//tll/llllll/llll/llll/ll/llllllllllllll/llllllllllllll/ll 

    . . . 

    . 10-2.   Mutexes 

    246 _______________________________Windows   

    . 10-2 () 
    
    II ,       
    DWORD WINAPI Counter-Thread (LPVOID IpThreadParameter) { 
    unsigned int nNumber, nDlgit; 
    BOOL fSyncChecked; 
    while (! g_rTerminate) { 
    
    //    Synchronize    
    fSyncChecked = IsDlgButtonChecked(g_hwnd, IDC_SYNCHRONIZE); 
    if (fSyncChecked) { 
    
    //     ,   
    WaitFor-SingleObject(&g_hMutex, INFINITE): 
    
    //          1 
    _stscanf(g_szNumber, __TEXT("%d"), &nNumber); 
    nNumber++; 
    
    //      
    nDigit = 0; 
    while (nNumber != 0) { 
    //      
    g_szNumber[nDigit++] = (TCHAR) (__('0') + (nNumber % 10)): 
    //    Sleep  ,   
    //        . 
    //        ,  
    //        
    // .   Sleep  , ,  . 
    Sleep(O); 
    
    //     
    nNumber /= 10; 
    } 
    
    //     ;   
    g_szNumber[nDigit] = 0; 
    
    //     ;  
    //  .  ANSI,  _strrev,   
    // Unicode,  - _wcsrev. 
    _tcsrev(g_szNumber); 
    if (fSyncChecked) { 
    //     ,   
    ReleaseMutex(g_hMutex): 
    \ 
    . . . 


    __________________________ 10.   247 


    . 10-2 () 
    
    //    -     
    //  ,   
    if (IsDlgButtonChecked(g_hwnd. IDC_SHOWCNTRTHRD)) 
    AddToListBox(__TEXT("Cnt : Increment")); 
    return(O); //       
    } 
    '' '' '! /.' !/: i' i!,! / /!! 111111111111! I! 11111111111111! :!    
!ii '.'     ':' 
    I / ,      
    // ( )    
    DWORD WINAPI DisplayThread (LPVOID IpThr-eadParameter) { 
    BOOL fSyncChecked; 
    TCHAR szBuffer[50J: 
    while (!g_fTerminate) { 
    
    // :     
    fSyncChecked = IsDlgButtonChecked(g_hwnd, IDC_SYNCHRONIZE); 
    if (fSyncChecked) 
    WaitForSingleObJect(&g_hMutex, INFINITE); 
    
    //       
    _stprintf(szBuffer, __TEXT("Dspy: %s"). g_szNumber); 
    if (fSyncChecked) 
    ReleaseMutex(&g_hMutex): 
    
    //      
    AddToListBox(szBuffer); 
    } 
    return(O); //       
    } 
    
    BOOL Dlg_OnlnitDialog (HWND hwnd, HWND hwndFocus, LPARAM IParam) { 
    HWND hWndGtl: 
    DWORD dwThreadID; 
    
    //      
    chSETDLGICONS(hwnd, IDI_MUTEXES, IDI_MUTEXES); 
    
    //       , 
    //        .   
    //    . 
    g_hwnd = hwnd; 

    . . . 

    248 ______________________________Windows   


    . 10-2 () 

    I I  -,    
    //  ,      - . 
    //     . 
    q_hMutex = CreateMutex(NULL, FALSE, NULL); 
    
    //     CounterThread    
    g_hThread[0] = chBEGINTHREADEX(NULL, , 
    CounterThread, NULL, 0, &dwThreadID); 
    
    //     OisplayThread    
    g_hThread[1] = chBEGINTHREADEX(NULL, , 
    DisplayThread, NULL, 0, &dwThreadID); 
    //    Process Priority Class 
    //   Normal 
    hWndCt! = GetDlgItem(hwnd, IDC_PRIORITYCLASS); 
    ComboBox_AddString(hWndCtl, __TEXT("Idle")); 
    ComboBox_AddString(hWndCtl, __TEXT("Normal")): 
    ComboBox_AddString(hWndCtI, __TEXT("High")); 
    ComboBox_AddString(hWndCtl, __TEXT("Realtime")); 
    ComboBox_SetCurSel(hWndCtl, 1); // Normal 
    //    Display Thread Priority 
    //   Normal 
    hWndCtI = GetDlgItem(hwnd, IDC_DSPYTHRDPRIORITY); 
    ComboBox_AddString(hWndCtl, __TEXT("Idle")); 
    ComboBox_AddStnng(hWndCtl, __TEXT(" Lowest")); 
    ComboBox_AddString(hWndCtl, TEXT( "Below normal")); 
    ComboBox_AddString(hWndCtl, _TEXT("Normal")); 
    ComboBox_AddString(hWndCtl, __TEXT("Above normal")); 
    ComboBox_AddString(hWndCtl, __TEXT("Highest")); 
    ComboBox_AddString(hWndCtl, __TEXT("Timecritical")); 
    ComboBox_SetCurSel(hWndCtl, 3); // Normal 
    //    Counter Thread Priority 
    //   Normal 
    hWndCtI = GetDlgItem(hwnd, IDC_CNTRTHRDPRIORITY); 
    ComboBox_AddString(hWndGtl, __TEXT("Idle")): 
    ComboBox_AddString(hWndCtl. __TEXT("Lowest")); 
    ComboBox_AddString(hWndCtl, __TEXT("Below normal")); 
    ComboBox_AddStnng(hWndCtl, __TEXT( "Normal")); 
    ComboBox_AddString(hWndCtl, __TEXT("Above normal")); 
    ComboBox_AddSt ring(hWndCtI, __TEXT("Highest")); 
    ComboBox_AddString(hWndCtl, __TEXT("Timecritical")); 
    ComboBox_SetCurSel(hWndCtl, 3); // Normal 
    return(TRUE); 
    } 
    llllllllllllllll//lll/llll/lllllll/IIIIHIIIIIIIIIIIIfll/lll^l/,i! /: 

    . . . 

    __________________________ 10.   249 


    . 10-2 () 

    void Dlg_OnDestroy (HWND hwnd) { 
    
    //    ,  ,   
    //   
    g_fTerminate = TRUE; 
    
    /   ,    
    ResumeThread(g_hThread[0]): 
    ResumeThread(g_hThread[1]); 
    i 
    
    /////////////////////////////////////////////////////////////////////////////// 
    void Dlg_OnCommand (HWND hwnd, int id, HWND hwndCtI, UINT codeNotify) { 
    HANDLE hThread; 
    DWORD dw; 
    
    switch (id) { 
    case IDCANCEL: 
    EndDialog(hwnd, id); 
    break; 
    case IDC_PRIORITYCLASS: 
    
    if (codeNotify != CBN_SELCHANGE) 
    break: 
    
    //     
    switch (ComboBox_GetCurSel(hwndCtl)) { 
    case 0: 
    dw = IDLE_PRIORITY_CLASS; 
    break; 
    case 1: 
    default: 
    dw = NORMAL_PRIORITY_CLASS; 
    break; 
    case 2: 
    dw = HIGH_PRIORITY_CLASS: 
    break; 
    case 3: 
    dw = REALTIME_PRIORITY_CLASS; 
    break; 
    } 
    SetPriorityClass(GetCurrentProcess(), dw); 
    break; 
    case IDC_DSPYTHRDPRIORITY; 
    case IDC_CNTRTHRDPRIORITY: 

    . . . 


    250 _______________________________Windows   


    . 10-2 () 
    
    if (codeNotify != CBN_SELCHANGE) 
    break; 
    
    switch (ComboBox_GetCurSel(hwndCtl)) { 
    case 0: 
    dw = (DWORD) THREAD_PRIORITY_1DLE; 
    break; 
    case 1: 
    dw = (DWORD) THREAD_PRIORITY_LOWEST; 
    break; 
    case 2: 
    dw = (DWORD) THREAD_PRIORITY_BELOW_NORMAL; 
    break; 
    case 3: 
    default: 
    dw = (DWORD) THREAD_PRIORITY_NORMAL; 
    break; 
    case 4: 
    dw = (DWORD) THREAD_PRIORITY_ABOVE_NORMAL; 
    break; 
    dw = (DWORD) THREAD_PRIORITY__HIGHEST: 
    break; 
    case 6: 
    dw = (DWORD) THREAD_PRIORITY_TIME_CRITICAL; 
    break; 
    //'     
    //    
    hThread = (id == IDC_CNTRTHRDPRIORITY) ? g_hThread[0] : g_hThread[1]; 
    SetThreadPriority(hThread, dw); 
    break; 
    case IDC_PAUSE: 
    
    //    
    //    

    . . . 


    __________________________ 10.   251 


    . 10-2 () 

    it (Bui:ton_GeLCneck(nwridCLl)} { 
    SuspendThread(g_hThread[0]); 
    SusndThread(g_hThread[1]); 
    } else { 
    ResumeThread(g_hThread[0]); 
    ResumeThread(g_hThread[1]); 
    } 
    break; 
    BOOL CALLBACK 01g_Proc (HWND hwnd. UINT uMsg, WPARAM wPararn, LPARAM 
IParam) { 
    switch (uMsg) { 
    chHANDLE_DLGMSG(hwnd. WM_INITOIALOG, Dlg_OnInitDialog); 
    chHANDLE_DLGMSG(hwnd. WM_DESTROY, Dlg_OnDestroy); 
    chHANOLE_DLGMSG(hwnd. WM_COMMAND, Dlg_OnComniand); 
    > 
    return(FALSE); 
    int WINAPI _tWinMain (HINSTANCE hinstExe, 
    HINSTANCE hinstPrev, LPTSTR pszCmdLine, int nCmdShow) { 
    chWARNIFUNICODEUNDERWIN95(); 
    DialogBox(hinstExe, MAKEINTRESOURCE(IDD_MUTEXES), NULL, Dlg_Proc); 
    
    //     
    WaitForMultipleOb]ects(2, g_hThread, TRUE, INFINITE); 
    
    //    
    CloseHandle(g_hThread[0]); 
    CloseHandle(g_hThread[1]); 
    
    //      , 
    //     
    CloseHandle(g_hMutex); 
    return(O); 
    [ 
    IIIIIIIIIIIIIIIIIHIiHIIIIIIIIII/   11111111111111111 I! 11111111 111111 


    252 ______________________________Windows   


     

          .   
    .      
,        1.  
     .  ,   
   ,    ,  
  ,     ,  
  .      
      - . 
    ,   3  ,     
   ,        
.       .  
   ,     
,  3 (      3).   
 ,    ,     0,  
,    0 ( 0    ).    
  WaitForSingkObject       
:   0     ?  ,  
  1   .    WaitForSingleObject  
  0,      ,    
  (. .    ). 
            , 
 (      )    
 - .  ,       
(   ),      (  
  ). 
       CreateSemaphore: 

    HANDLE CreateSemaphore(LPSECURITY_ATTRIBUTE Ipsa, 
    LONG cSemInitial, LONG cSemMax, LPTSTR IpszSemName); 

       ,      
 cSemMax.          
 3 (  ).  cSemInitial   
  .       
 , ,      3.     
    ,    ,    
 0. 
      , IpszSemName,     
_.          
    CreateSemaphore  OpenSemaphore: 

    HANDLE OpenSemaphore(DWORD fdwAccess, BOOL finherit, LPTSTR IpszName): 

           OpenMutex. 
          (   
),  ReleaseSemaphore: 

    BOOL ReleaseSemaphore(HANDLE hSemaphore, LONG cRelease, LPLONG IplPrevious); 

       ReleaseMutex,    . -,   
    ,       
-  . -,       
    1 .  cRelease    
,     . ,    
,        .  
     , 

    __________________________ 10.   253 

       WaitForSingleObject.     
     ReleaseSemaphore.    : 
    
    //     
    WaitForSingleObject(g_hSemSerialPort, INFINITE): 
    WaitForSingleObject(g_hSemSerialPort, INFINITE): 
    // -    
    
    //   ,    
    //     
    ReIeaseSemaphore(g_hSemSerialPort, 2, NULL): 

      ,        
WaitForSingleObject     WaitForMultipleObjects.   
        . 
 ,          . 
       ReleaseSemaphore IplPrevious   
  LONG,      , 
 ,       cRelease.   
   ,    IplPrevious  NULL. 
         \32-,     
 ,    .   ,   
ReleaseSemaphore           
     LONG,     
IplPrevious.   ;    0.     
   ,     .    : 
 _,  1_,. 

    -  

     SprMrkt (SPRMRKT.EXE) (.   . 10-4)  
     -  . 
        SPRMRKT  -, 
  .        : 

    254 _______________________________Windows   

          ,  
  .  ,   Open For 
Business ( )      ,  
,    . ,   , 
 ThreadSuperMarket. 
         : 
    1.  . 
    2.  ,   . 
    3.        ( 
       ). 
    4.     ,   
    . 
    5.  GUI- (  )   
          
        . 
    .   -   -,  
   _ begin threadex-.                             "'" 

    hThread = (HANDLE) chBEGINTHREADEX { 
    NULL,                  //   
    ,                     //  
    ThreadShopper,         //   
    (LPVOID) ++nShopperNum,//    IpvParam 
    0.                     //  
    &i1wThrpadTcl)            //   
    CloseHandle(hThread); 

     CloseHandle  ,  -   
  -.    -  
    .  ,   
,   ,    ,  
     . 
    ,    ,    ,   
 CloseHandle. :  .      
         , 
 1. ,   chBEGINTHREADEX3   
 ,      2.   
   (. .   ),   
      1.     
  CloseHandle,     ,     
       .    
-         
    ,    ,   
       .  
,  CloseHandle  . 
    -  -    
.         
 Shopper Create Delay (    ). 
     ,  ,    , 
 ,   ,   ,   
       . 
    3. chBEGINTHREADEX ,   _beginthreadex  
  .      , 
  .       
CmnHdr.h,    -,   .  
.  . 

    ___________________________ 10.   255 

       : 
    1.    . 
    2.    . 
    3.       - . 
    4.     . 
    5.      . 
    6.   . 
    7.   . 
           . 
          Shopper Events (,  
 )    ,    .   
,            
 (      
).    ,   ,  
         
    .  . 10-3  
    ,    . 

    ---> Opening the supermarket to shoppers. 
    0001: Waiting to get in store (11), 
    0002: 'WaTting to get in store (16). 
    0001: In supermarket, shopping for 46. if 
    0002: In supermarket, shopping for 38. 
    0003: Waiting to get in store (17). 
    0003: In supermarket, shopping for 65. 
    0002: Not going to to the deli counter. 
    0001: Waiting for service at deli counter (17). - 
    0002: Waiting for an empty checkout counter. 
    0001: Being served at deli (49). 
    0002: Checking out (30). 
    0003: Waiting for service at deli counter (0). 
    0003: Tyred of waiting at deli. 
    0004; Waiting to get in store (7). 
    0002: Leaving checkout counter. 
    0001: Waiting for an empty checkout counter. 
    0005: Waiting to get in store (3). 
    0003: Waiting for an empty checkout counter. 
    0004: In supermarket, shopping for 9, 
    0006: Waiting to get in store (8). 
    0002: Left the supermarket. 
    0001: cHecking out (0). 
    0005: In supermarket, shopping for 0. 
    0003: Checking out (22). 
    0006: In supermarket, shopping for 42. 
    0004: Not going to the deli counter. 
    0001: Leaving checkout counter. 
    0005: Not going to the deli counter. 

    . . . 

    . 10-3.     ,  
      

    256 _______________________________Windows   

    . 10-3 () 

    0003: Leaving checkout counter. 
    0004: Waiting for an empty checkout counter. 
    0001: Left the supermarket. 
    0005: Waiting for an empty checkout counter. 
    0004: Checking out (36). 
    0003: Left the supermarket. 
    0006; Waiting for service at deli counter (13). 
    0007: Waiting to get in store (7). 
    0005: Checking out (3). 
    0006; Being served at deli (42). 
    0004: Leaving checkout counter. 
    0007: In supermarket, shopping for 41. 
    0008: Waiting to get in store (16). 
    0005: Leaving checkout counter. 
    0006: Waiting for an empty checkout counter, 
    0005: Left the supermarket, 
    0004: Left the supermarket. 
    0008: In supermarket, shopping for 24. 
    0007: Not going to the deli counter. 
    0006: Checking out (43). 
    0007: Waiting for an empty checkout counter. 
    0008: Not going to the deli counter. 
    0007: Checking out (8). 
    0009: Waiting to get in store (10). 
    0008: Waiting for an empty checkout counter. 
    0008: Checking out (27). 
    0006: Leaving checkout counter. 
    0009; In supermarket, shopping for 18. 
    0007: Leaving checkout counter. 
    0006: Left the supermarket, 
    0007: Left the supermarket. 
    0009: Not going to the deli counter. 
    0008: Leaving checkout counter. 
    0008: Left the supermarket. 
    0009: Waiting for an empty checkout counter. 
    0009: Checking out (46). 
    0010: Waiting to get in store (16). 
    0010: In supermarket, shopping for 79. 
    0009; Leaving checkout counter. 
    0009: Left the supermarket. 
    0011: Waiting to get in store (12), 
    : In supermarket, shopping for 31. 
    0010: Waiting for service at deli counter (5), 
    : Not going to the deli counter. 
    0010; Being served at deli (1). 
    : Waiting for an empty checkout counter. 
    0010: Waiting for an empty checkout counter. 
    0010: Checking out (22). 
    : Checking out (5). 

    . . . 

    _________________________ 10.   257 


    . 10-3 () 

    0012: Waiting to get in store (1). 
    0011: Leaving checkout counter 
    0010: Leaving checkout counter. 
    0012; In supermarket, shopping for 0. 
    : Left the supermarket. 
    0010: Left the supermarket. 
    0012: Not going to the deli counter. 
    0013: Waiting to get in store (5). 
    0012: Waiting for an empty checkout counter. 
    0012: Checking out (35), 
    0013: In supermarket, shopping for 55. 
    0014: Waiting to get in store (14), 
    0014: In supermarket, shopping for 38. 
    0012: Leaving checkout counter. 
    0013: Waiting for service at deli counter (14). 
    0013: Being served at deli (32). 
    0012: Left the supermarket. 
    0014: Waiting for service at dell counter (18). 
    0013: Waiting for an empty checkout counter. 
    0014: Tired of waiting at deli. 
    0014: Waiting for an empty checkout counter. 
    0015: Waiting to get in store (2). 
    0013: Checking out (35). 
    0014: Checking out (23). 
    0015; In supermarket, shopping for 58. 
    0013: Leaving checkout counter. 
    0013: Left the supermarket. 
    0014: Leaving checkout counter. 
    0015: Not going to the deli counter, 
    0014: Left the supermarket. 
    0015; Waiting for an empty checkout counter, 
    0016: Waiting to get in store (7). 
    0015: Checking out (9). 
    0016; In supermarket, shopping for 18. 
    0015: Leaving checkout counter. 
    0015: Left the supermarket. 
    0016; Waiting for service at deli counter (16). 
    0016: Being served at deli (36). 
    0017: Waiting to get in store (15). 
    0016; Waiting for an empty checkout counter. 
    0017: In supermarket, shopping for 27. 
    0016: Checking out (10), 
    0017: Not going to the deli counter. 
    0016: Leaving checkout counter. 
    0017: Waiting for an empty checkout counter. 
    0017: Checking out (29). 
    0016: Left the supermarket. 
    0017: Leaving checkout counter. 
    0017: Left the supermarket. 

    . . . 

    258 _______________________________Windows   


    . 10-3 () 

    0018; Waiting to get in store (13). 
    0018: In supermarket, shopping for 75. 
    0019: Waiting to get in store (2). 
    0019; In supermarket, shopping for 11. 
    0019: Not going to the deli counter. 
    0018: Not going to the deli counter. 
    0020: Waiting to get in store (8). 
    0019: Waiting for an empty checkout counter. 
    0018: Waiting for an empty checkout counter. 
    0019: Checking out (4). 
    0020: In supermarket, shopping for 54. 
    0021: Waiting to get in store (3). 
    0018: Checking out (52). 
    . 0019: Leaving checkout counter, 
    0021: In supermarket, shopping for 65, 
    0019: Left the supermarket. 
    0020: Not going to the deli counter. 
    0020: Waiting for an empty checkout counter. 
    0018; Leaving checkout counter. 
    0021: Waiting for service at deli counter (3). 
    : 0020: Checking out (49). 
    0018: Left the supermarket. 
    0021: Being served at deli (35). 
    0022: Waiting to get in store (3). 
    0020: Leaving checkout counter, 
    0020: Left the supermarket, 
    0021: Waiting for an empty checkout counter. 
    0022: In supermarket, shopping for 58. 
    0023: Waiting to get in store (5). 
    0021: Checking out (34). 
    0023: In supermarket, shopping for 54, 
    0022: Not going to the deli counter. 
    0024: Waiting to get in store (9). 
    0021: Leaving checkout counter. 
    0023: Waiting for service at deli counter (7). 
    0022; Waiting for an empty checkout counter. 
    0024: In supermarket, shopping for 66. 
    0021: Left the supermarket. 
    0023: Being served at deli (2). 
    0022: Checking out (31), 
    0023: Waiting for an empty checkout counter. 
    0022: Leaving checkout counter. 
    0024: Not going to the deli counter. 
    0023: Checking out (56). 
    0025: Waiting to get in store (2). 
    0022: Left the supermarket. 
    0024: Waiting for an empty checkout counter. 
    0025: In supermarket, shopping for 73. 
    0024: Checking out (32), 

    . . . 

    ___________________________ 10.   259 


    . 10-3 () 

    0023: Leaving checkout counter. 
    0026: Waiting to get in store (9). 
    0023: Left the supermarket. 
    0025; Waiting for service at deli counter (16). 
    0024: Leaving checkout counter. 
    0026: In supermarket, shopping for 21. 
    0027: Waiting to get in store (9). 
    0025: Being served at deii (68). 
    0024: Lett the supermarket. 
    0027: In supermarket, shopping for 45. 
    0028: Waiting to get in store (14). 
    0026: Waiting for service at deli counter (15). 
    0025: Waiting for an empty checkout counter. 
    0028: In supermarket, shopping for 67. 
    0026: Being served at deii (27). 
    0029: Waiting to get in store (17). 
    0027: Waiting for service at deli counter (19). 
    0025: Checking out (34). 
    0026: Waiting for an empty checkout counter. 
    0029: In supermarket, shopping for 4. 
    0028: Not going to the deli counter. 
    ---> Waiting for shoppers to check out so store can close. 
    0027: Being served at deli (13). 
    0025: Leaving checkout counter, 
    0026; Checking out (50), 
    ---> 0 shoppers NOT in store. 
    0028: Waiting for an empty checkout counter. 
    0029; Not going to the deli counter. 
    0027: Waiting for an empty checkout counter, 
    ---> 1 shoppers NOT in store. 
    0025: Left the supermarket. 
    0028: Checking out (39). 
    0027: Checking out (11), 
    0029: Waiting for an empty checkout counter. 
    0026: Leaving checkout counter. 
    ---> 2 shoppers NOT in store. 
    0027: Leaving checkout counter. 
    ---> 3 shoppers NOT in store. 
    0029: Checking out (50). 
    0026: Left the supermarket. 
    0028: Leaving checkout counter. 
    0027: Left the supermarket. 
    ---> 4 shoppers NOT in store, 
    0028: Left the supermarket. 
    0029: Leaving checkout counter. 
    ---> 5 shoppers NOT in store. 
    0029: Left the supermarket. 
    ---> 6 shoppers NOT in store. 
    -"> 7 shoppers NOT in store, 


    . . . 

    260 _______________________________Windows   

    PUC. 10-3 () 

    ---> 8 shoppers NOT in store. 
    ---> 9 shoppers NOT in store. 
    ---> 10 shoppers NOT in store. 
    ---> 11 shoppers NOT in store. 
    ---> 12 shoppers NOT in store. 
    ---> 13 shoppers NOT in store, 
    ---> 14 shoppers NOT in store. 
    ---> 15 shoppers NOT in store. 
    ---> 16 shoppers NOT in store. 
    ---> 17 shoppers NOT in store, 
    ---> 18 shoppers NOT in store. 
    ---> 19 shoppers NOT in store. 
    ---> 20 shoppers NOT in store. 
    ---> 21 shoppers NOT in store. 
    ---> 22 shoppers NOT in store. 
    ---> 23 shoppers NOT in store. 
    ---> 24 shoppers NOT in store. 
    ---> 25 shoppers NOT in store, 
    ---> 26 shoppers NOT in store. 
    ---> 27 shoppers NOT in store. 
    ---> 28 shoppers NOT in store. 
    ---> 29 shoppers NOT in store. 
    ---> Store closedend of simulation. 

     ,         
.  ,   ,    ,  
 -   .     
  . 
     , -     , 
   g_hSemEntrance: 

    g_hSemEntrance = CreateSemaphore( 
    NULL,               //   
    ,                  //      
    g_nMaxOccupancy,    //   ,  
    //     
    NULL):              //    

           , 
    .     
    Maximum Occupancy. -      
       ,   
  .        0 
(   ).     , 
  : 

    ReleaseSemaphore(g_hSemEntrance, g_nMaxOccupancy, NULL): 

       -,  ,   ,   
 WaitForSingleObject 

    dwResult = WaitForSingleObject(g_hSemEntrance, nDuration); 

         g_nMaxOccupancy ,  
- .        
 (g_nMaxOccupancy), 

    _________________________ 10.   261 

    WaitForSingleObject   ,   
   .       , 
,     . 
     ,         
nDuratiori?         , 
     .     
       Wait To Get In Market ( 
   ).       , 
WaitForSingleObject   WAIT_TIMEOUT. -  
       Shopper Events  . 
      ,  - .  
        Time To 
Shop (,   ).     
-   :    Sleep  
  ,   . 
        (   Sleep),    
    -  ( ,  ,     
  ). ,     , ,   
,      .     
          (  ). 
             ,   
.        . 
  -  -  
  -.        - 
 -.        ,   
  ,        ,  
     , . .  -.  
      ,     
,   Sleep      , 
       Time At Deli 
Counter (,    ). 
      ,     ,   
       .   
        Wait For Deli Counter 
(   ). 
         . -,     
.     ,    
 .       
.      ,    
 -,    ,  , 
         
 .     ,      
   . 
     :        
,      .  ,   1  
 ,     2    
   3, ,    ,  2  3 
-  -.     ,  
    2  - ,     
. ,        , 
      .   
,  Win32 API      
 . 
                  
  .         
Checkout Counters ( ). 

    262 ____________________________Windows   

        ,      .  
    ,      
  ,        . 
        . ,  
,      . 
        , , .    
    ,    , ,   
  .    ,  ,  
,    ,  .      
   .      
 .   ,  ,  : 

    g_hSeniCheckout = CreateSemaphore( 
    NULL,                  //   
    g_nCheckoutRegisters,  //    
    g_nCheckoutRegisters,  //     
    NULL);                 //    

         ,     
.   ,   ,   
   1.    ,   
.    ,       
 ,        .   
-    ,      : 

    WaitForSingleObject(g_hSemCheckout, INFINITE); 

        , -     
   .       Sleep, 
   ,      
  Time At Checkout (   ). 
    ,    ,      g_hSemCheckout 

    ReieaseSemaphore(g_hSemCheckout, 1, NULL); 

       ,   ,   . 
    ,    g_hSemEntrance: 

    ReleaseSemaphore(g_hSemEntrance, 1, NULL); 

       ,     
,         . 
          . 
      , ,     -   
 -.    , -   
  -.     
,       Time Open ( ). 
    ,     , -  
  .    ,   
       .    
  : 

    for (nMaxOccupancy = 0; 
    nMaxOccupancy < g_nMaxOccupancy; nMaxOccupancy++) { 
    WaitForSingleObject(g_hSemEntrance, INFINITE): 
    } 

     -   WaitForSingleObject   
,  -     ^nMaxOccupancy ;  
  

    ___________________________ 10.   263 

       ,     .   
  ,  -     
 .        -, 
 -. ,   ,  ,   
   .  ,  ,  
      . 
       ,  -  ,  
,   .     ,   
        ,   
, .       
    . 
    ,         - 
 WaitForMultipleObjects, .     
WaitForSingleObject.      ._-,  
     WaitForMultipleObjects   
. -,       MAXIMUM_WAIT_OBJECTS (. 
. 64) .    ,     
WaitForMultipleObjects . 
       g_nMaxOccupancy , -   
,      : 

    CloseHandle(g_hSerriCheckout): 
    CloseHandle(g_hMtxOeliCntr); 
    CloseHandle(g_hSemEntrance); 
    SPRMRKT.C 
    : SprMrkt.C 
    : Copyright  1995-1997,   (Jeffrey Richter) 
    Sinclude "..\CmnHdr.H"           /* .   */ 
    ftinclude <windows,h> 
    ftinclude <windowsx.h> 
    #include <tchar.h> 
    ffinclude <stdio,h> 
    #include <stdlib.h>              //     
    #lnclude <string.h> 
    #include <stdarg.h> 
    ftinclude <process.h>             //  _beginthreadex 
    #include "Resource.H" 
    //'     ""  windowyx.n 
    #undef FORWARD_WM_HSCROLL 
    ffdefine FORWARD_WM_HSCROLL(hwnd, hwndGtl, code, pos, fn) \ 
    (void)(fn)((hwnd), WM_HSCROLL, \ 
    MAKEWPARAM((UINT)(code),(UINT)(pos)), \ 
    (LPARAM)(UINT)(hwndCtl)) 
    /// ii/llllllll/lll/llllllliti //a. .'//,1'//,',-1/ 1  - yy/y      
 ' i'1 
    . . . 
    . 10-4.   SprMrkt 

    264 ______________________________Windows   
    . 10-4 () 
    II     ,   
    //   
    DWORD WINAPI ThreadSuperMarket (LPVOID IpvParam); 
    DWORD WINAPI ThreadShopper (LPVOID IpvParam); 
    /' ' I ! ! 1 / / ! / 1 ' I I !' I I ! ! I I I I I / ! / I I ' / I I I I ! 
I I ! I / I ! / / I I / ' ! I ' ' / ' / ! ' / ':    ,  ! ' ,;'1, .' '    1 
,',''                                ':' 
    //   
    
    HWND g_hwndLB = NULL;  //     , 
    //    
    
    //  ,   
    int g_nMaxOccupancy: 
    
    int g_nTimeOpen;                                                           
                  ' 
    int g_nCheckoutCounters;                                                   
                 :: 
    int g_nMaxDelayBetweenShopperCreation: 
    int g_nMaxWaitToGetInMarket; 
    int g_nMaxTime8hopping; 
    int g_nMaxWaitForDeliCntr; 
    int g_nMaxTimeSpentAtDeli; 
    int g_nMaxTimeAtCheckout: 
    
    //  ,     
    HANDLE g_hSemEntrance; 
    HANDLE g_hMtxDeliCntr; 
    HANDLE g_hSernCheckout; 
    //   (   )  . 
    //   ,      ,   
    //    g_hwndLB 
    void AddStr (LPCTSTR szFnit, .,.) { 
    TCHAR szBuf[150]; 
    int nindex: 
    va_list va_params; 
    
    //  ,  va_params      szFmt 
    va_start(va_params, szFmt); 
    //    
    _vstprintf(szBuf, szFmt, va_params);                                       
              .1 
    do {                                                                       
                        'I 
    //      
    nindex = ListBox_AddString(g_hwndLB, szBuf); 
    //    ,      
    if (nindex == LB_ERR) 
    ListBox_DeleteString(g_hwndLB, 0); 
    } while (nindex ==.LB.ER.R); 


    __________________________ 10.    265 


    . 10-4 () 
    
    / I       
    ListBox_SetCurSel(g_hwndLB, nindex): 
    // ,       
    va_end(va_params); 
    ^ 
    /1111/1///1/1///1/1//11//1111/1//111////11/1/1//11/11/1111111111/1111111/11 
    / /         0  nMaxValue 
    //  
    int Random (int nMaxValue) { 
    return(rand() / (RAND_MAX / (nMaxValue + 1))); 
    } 
    
    l//lll/ll///ll//ill///llll//l/l/ll//llllllllll/l/lll//ll//ll////l/llllll/l/llll 
    BOOL Dlg_0nlnit0ialog (HWND hwnd, HWND hwndFocus, LPARAM IParam) { 
    HWND hwndSB; 
    
    //      
    chSETDLGICONS(hwnd, IOI_SPRMRKT, IDI_SPRMRKT); 
    
    //       ,  
    //  AddStr      
    g_hwndLB = Get01gltem(hwnd, IDC_SHOPPEREVENTS); 
    //         
    //    
    hwndSB = Get01gltem(hwnd, IDC_MAXOCCUPANCY); 
    ScrollBar_SetRange(hwndSB, 0, 500, TRUE); 
    
    //        
    FORWARD_WM_HSCROLL(hwnd, hwndSB, SB_THUMBTRACK, 30, SendMessage); 
    hwndSB = Get01gltem(hwnd, IDC_TIMEOPEN): 
    ScrollBar_SetRange(hwndSB, 0, 5000, TRUE); 
    FORWARD_WM_HSCROLL(hwnd, hwndSB, SB_THUMBTRACK, 5000, SendMessage); 
    hwndSB = GetDlgItem(hwnd, IDC_NUMCOUNTERS): 
    ScrollBar_SetRange(hwndSB, 0, 30, TRUE); 
    FORWARD_WM_HSCROLL(hwnd, hwndSB, SB_THUMBTRACK, 5, SendMessage); 
    hwndSB = GetDlgItem(hwnd, IDC_SHOPPERCREATIONDELAY); 
    ScrollBar_SetRange(hwndSB, 0, 1000, TRUE); 
    FORWARD_WM_HSCROLL(hwnd, hwndSB, SB_THUMBTRACK, 300, SendMessage); 
    hwndSB = GetDlgItem(hwnd, IDC_DELAYTOGETIN); 
    ScrollBar_SetRange(hwndSB, 0, 100, TRUE); 
    FORWARD_WM_HSCROLL(hwnd, hwndSB, SB_THUMBTRACK, 20, SendMessage); 


    266 _______________________________Windows   


    . 10-4 () 

    hwndSB = GetDlgItem(hwnd, IDC_TIMETOSHOP); 
    ScrollBar_SetRange(hwndSB, 0, 100, TRUE): 
    FORWARD_WM_HSCROLL(hwnd, hwndSB, SB_THUMBTRACK, 80, SendMessage); 
    hwndSB = GetDlgItem(nwnd, IDC_WAITDELICNTR); 
    ScrollBar_SetRange(hwndSB, 0, 100, TRUE); 
    FORWARD_WM_HSCROLL(hwnd, hwndSB, SB_THUMBTRACK, 20, SendMessage): 
    hwndSB = GetDlgItern(hwnd, IOC_TIMEATDELICNTR): 
    ScrollBar_SetRange(hwndSB, 0, 100, TRUE); 
    FORWARD_WM_HSCROLL(hwnd, hwndSB, SB_THUMBTRACK, 70, SendMessage); 
    hwndSB = GetDlgItem(hwnd, IDC_TIMEATCHECKOUT); 
    ScrollBar_SetRange(hwndSB, 0, 100, TRUE): 
    FORWARD_WM_HSCROLL(hwnd, hwndSB, SB_THUMBTRACK, 60, SendMessage); 
    return(TRUE); 
    } 
    !!!ll/llll|llll/!/ii!ii!///!l/l/il/li/l/ill|||||/|||||lll/ll!lll^'l|l||lil|//! 
    void Dlg_OnHScroll(HWND hwnd. HWND hwndCtI, UINT code, int pos) { 
    TCHAR szBuf[10]: 
    int nPosCrnt, nPosMin, nPosMax; 
    
    //         
    // ,      
    nPosCrnt = ScrollBar_GetPos(hwndCtl); 
    ScrollBar_GetRange(hwndGtl, SnPosMin, &nPosMax); 
    switch (code) { 
    case SB_LINELEFT: 
    nPosCrnt--; 
    break; 
    case SB_LINERIGHT: 
    nPosCrnt++; 
    break; 
    case SB_PAGELEFT: 
    nPosCrnt -= (nPosMax - nPosMin + 1) / 10; 
    break; 
    case SB_PAGERIGHT: 
    nPosCrnt += (nPosMax - nPosMin + 1) / 10; 
    break; 
    case SB_THUMBTRACK: 
    nPosCrnt = pos: 
    break; 

    __________________________ 10.    267 


    . 10-4 () 

    case SB_LEFT: 
    nPosCrnt = nPosMin; 
    break; 
    case SB_RIGHT: 
    nPosCrnt = nPosMax; 
    break; 
    
    // ,      
    //    
    if (nPosCrnt < nPosMin) 
    nPosCrnt = nPosMin; 
    
    if (nPosCrnt > nPosMax) 
    nPosCrnt = nPosMax; 
    
    //      
    ScrollBar_SetPos(hwndCtl, nPosCrnt, TRUE); 
    
    //  ,     (), 
    //          
    _stprintf(szBuT, __TEXT("%d"), nPosCrnt); 
    SetWindowText(GetPrevSibling(hwndCtl), szBuf); 
    i 
     
    /////////////////////////////////////////////////////////////////////////////// 
    void Dlg_OnCommand (HWND hwnd, int id, HWND hwndCtI, UINT codeNotify) { 
    DWORD dwThreadId; 
    HANDLE hThread; 
    switch (id) { 
    case IDOK: 
    
    //       , 
    //      
    g_nMaxOccupancy = ScrollBar_GetPos( 
    GetDlgItem(hwnd, IDC_MAXOCCUPANCY)); 
    
    g_nTimeOpen = ScrollBar_GetPos( 
    GetDlgItem(hwnd, IDC_TIMEOPEN)); 
    
    g_nCheckoutCounters = ScrollBar_GetPos( 
    GetDlgItem(hwnd, IDC_NUMCOUNTERS)); 
    
    g_nMaxDelayBetweenShopperCreation = ScrollBar_GetPos( 
    GetDl9ltem(hwnd, IDC_SHOPPERCREATIONDELAY)); 
    g_nMaxWaitToGet!nMarket = ScrollBar_GetPos( 
    GetDlgItem(hwnd, IDC_DELAYTOGETIN)): 


    268 ______________________________Windows   


    . 10-4 () 
    
    g_nMaxTlmeShopping = ScrollBar_GetPos( 
    Get01gltem(hwnd, IDC_TIMETOSHOP)); 
    
    9_nMaxWaitForDeliCntr = ScrollBar_GetPos( 
    GetDlgItem(hwnd, IDC_WAITOELICNTR)); 
    
    
    g_nMaxTimeSpentAtDeli = ScrollBar_GetPos( 
    Get01glte[fl(hwnd, IDC_TIMEATDELICNTR)): 
    
    
    g_nMaxTimeAtCheckout = ScrollBar_GetPos( 
    Get01gltem(hwnd, IDC_TIMEATCHECKOUT)): 
    
    
    //    
    ListBox_ResetContent(GetDlgItem(hwnd, IDC_SHOPPEREVENTS)); 
    
    
    //   Open For Business,   
    //   
    EnableWindow(hwndCtl, FALSE); 
    
    
    if (NULL == GetFocusO) { 
    
    
    SetFocus(GetDlgItem(hwnd, IDC_MAXOCCUPANGY)); 
    
    } 
    
    
    //     : 
    
    
    // ,      ,  
    //     
    SetPriorityClass(GetCurrentProcess(), HIGH_PRIORITY_CLASS); 
    
    
    //  - 
    hThread = chBEGINTHREADEX( 
    
    
    NULL,               //   
    
    
    ,                  //  
    
    
    ThreadSuperMarket, //   
    
    
    (LPVOID) hwnd,      //    
    
    
    ,                  //  
    
    
    SdwThreadId);       //   
    
    
    //         
    //  "",     
    CloseHandle(hThread); 
    
    
    break: 
    
    
    case IDCANCEL: 
    
    
    EndDialog(hwnd, id): 
    
    
    break; 
    
    
    } 
    
    
    /////////////////////////////////////////////////////////////////////////////// 
    
    
    . . cinr 

    ___________________________ 10.   269 


    . 10-4 () 

    BOOL CALLBACK Dlg_Proc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM 
IParam) { 
    switch (uMsg) { 
    chHANDLE_DLGMSG(hwnd, WM_INITDIALOG, Dlg_OnInitDialog): 
    chHANDLE_DLGMSG(hwnd, WM_COMMAND, Dlg_OnCommand); 
    chHANDLE_DLGMSG(hwnd. WM_HSCROLL, Dlg_OnHScroll); 
    case WM_USER: 
    
    //     SuperMarketThread,  
    //       
    
    //       
    SetPnorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS); 
    
    //   Open For Business,    
    //      
    EnableWindow(GetDlgItem(hwnd, IDOK), TRUE); 
    break; 
    returntFALSE); 
    } 
    int WINAPI _tWinMain (HINSTANCE hinstExe, 
    HINSTANCE hinstPrev, LPTSTR pszCmdLine, int nCmdShow) < 
    chWARNIFUNICODEUNDERWIN95(); 
    DialogBox(hinstExe, MAKEINTRESOURCE(IDD_SPRMRKT), NULL, Dlg_Proc); 
    return(O); 
    
    DWORD WINAPI ThreadSuperMarket (LPVOID IpvParam) { 
    DWORD dwCloseTime; 
    HANDLE hThread; 
    DWORD dwThreadId; 
    int nShopperNum = 0, nMaxOccupancy; 
    g_hSemEntranee = Create8emaphore( 
    NULL,                  //   
    ,                     //      
    g_nMaxOccupancy,       //   ,   
    
    //    
    NULL):                 //    
    g_hMtxDeUCntr = CreateMutex( 
    NULL,                  //   

    . . . 


    270 _______________________________Windows   


    . 10-4 () 
    
    FALSE,                 //       
    NULL);                 //    
    
    Q_hSemCheckout = CreateSe(naphore( 
    
    NULL.                  //   
    g_nCheckoutCounfers,   //    
    g_nCheckoutCounters,   //     
    NULL):                 //    
    
    //     
    AddStr(__TEXT("---> Opening the supermarket to shoppers.")): 
    ReleaseSemaphore(g_hSemEntrance, g_nMaxOccupancy, NULL); 
    //  ,      
    // - 
    dwCloseTime = GetTickCount() + g_nTimeOpen: 
    
    //  ,     
    while (GetTickCount() < dwCloseTime) { 
    
    //  - 
    hThread = chBEGINTHREADEX( 
    NULL,                  //   
    ,                      //  
    ThreadShopper,         //   
    (LPVOID) ++nShopperNum,//    IpvParain 
    ,                      //  
    &dwThreadId);          //   
    
    
    //         
    //  "",     
    CloseHandle(hThread): 
    
    
    // ,        
    Sleep(Random(g_nMaxDelayBetweenShopperCreation)); 
    
    
    //   ;     
    AddStr(__TEXT("---> Waiting for shoppers to check out ") 
    __TEXT("so store can close.")); 
    
    
    nMaxOccupancy = 1; 
    
    
    for (; nMaxOccupancy <= g_nMaxOccupancy; nMaxOccupancy++) { 
    WaitForSingleObject(g_hSemEntranee, INFINITE); 
    
    
    AddStr(__TEXT("---> %d shoppers NOT in store."). nMaxOccupancy); 
    
    
    } 
    
    . . . 

    __________________________ 10.   271 

    . 10-4 () 
    
    AudSLi (1---/ Store closedend  Simula Lion' )); 
    
    
    //   -   
    CloseHandle(g_hSemCheckout); 
    
    
    CloseHandle(g_hMtxDeliCntr): 
    
    
    CloseHandle(g_hSemEntranee); 
    
    
    //  GUI-,   .  
    //  ,  GUI-,   
    //  IpvParam       . 
    SendMessage((HWND) IpvParam, WM_USER, 0, 0); 
    
    
    return(O); 
    
    
    DWORD WINAPI ThreadShopper (LPVOID IpvParam) { 
    int nShopperNum = (int) IpvParam; 
    
    
    DWORD dwResult: 
    
    
    int nDuration; 
    
    
    //       l'lOIu^a;   
    // -        
    //       
    srand(GetTickCount() * nShopperNum); 
    
    
    // ,      
    nDuration = Random(g_nMaxWaitToGetInMarket); 
    
    
    AddStr(__TEXT("%041u: Waiting to get in store (%lu),"), nShopperNum, nDuration); 
    
    
    dwResult = WaitForSingleObject(g_hSemEntrance, nDuration); 
    
    
    if (dwResult == WAIT_TIMEOUT) { 
    
    
    //       
    
    AddStr(_J~EXT("%041u: Tired of waiting; went home."), 
    
    
    nShopperNum); 
    
    
    return(O); 
    
    
    //    ;    
    nDuration = Random(g_nMaxTimeShopping); 
    
    
    AddStr(__TEXT("%041u: In supermarket, shopping for %lu."), nShopperNum, nDuration); 
    
    
    Sleep(nDuration); 
    
    
    . . . 


    272 _______________________________Windows   


    . 10-4 () 
    
    II  .   ,      
    if (Random(2) == 0) { 
    
    
    // -  
    nDuration = Random(g_nMaxWaitForDeliCntr); 
    
    
    AddStr( 
    
    
    __TEXT("%041u: Waiting for service at ") 
    
    
    __TEXT("Deli Counter (%lu)."), 
    
    
    nShopperNum, nDuration); 
    
    
    dwResult = WaitForSingleObject(g_hMtxDeliCntr. nDuration); 
    
    
    if (dwResult == 0) { 
    //   
    nDuration = Random(g_nMaxTimeSpentAtDeli); 
    
    
    AddStr(__TEXT("%041u: Being served at Dell (%lu)."), nShopperNum, nDuration); 
    
    
    Sleep(nDuration); 
    
    
    //   
    ReleaseMutex(g_hMtxDeliCntr): 
    
    
    } else { 
    
    
    //  ,   
    
    
    Add8tr(__TEXT("%041u: Tired of waiting at Deli."), nShopperNum); 
    
    
    i 
    
    
    } else { 
    
    AddStr(__TEXT("%041u: Not going to the Deli counter."), nShopperNum); 
    
    
    //      
    AddStr(__TEXT("%041u: Waiting for an empty checkout counter."), nShopperNum); 
    
    
    WaitForSingleObject(g_hSemCheckout, INFINITE); 
    
    
    //  
    nDuration = Random(g_nMaxTimeAtCheckout); 
    
    
    AddStr(__TEXT("%041u: Checking out (%lu)."), nShopperNum, nDuration); 
    
    
    Sleep(nDuration); 
    
    
    //    
    AddStr(__TEXT("%041u: Leaving checkout counter."), nShopperNum); 
    
    
    ReleaseSemaphore(g_hSemCheckout, 1, NULL); 
    
    
    //    
    AddStr(__TEXT("%041u: Left the supermarket."), nShopperNum); 
    
    
    ReleaseSemaphore(g_hSemEntrance, 1, NULL); 
    
    
    // .  -. 
    
    
    return(O); 
    
    
    \ 
    
    IIIIIIIIIIIIIIII/HIIIIIIIIIHIIII   I /1111 /1111  11111 /1 H 


    __________________________ 10.   273 


     

          ,  
    .     
    ,       
- .     :    
(manual-reset events)    (auto-reset events).   
      ,     . 
         ,  -   
,     ,     
.         
    .      
   .        
        .   
   ,     
 . 
    ,     .     
     ,     . 
 ,    ,     
       . . 
       .  ,   , 
   ,   
-  .    CreateEvent 

    HANDLE CreateEvent(LPSECURITY_ATTRIBUTES Ipsa, BOOL fManualReset, 
    BOOL fInitialState, LPTSTR IpszEventNaine); 

     fManualReset ( )  ,   
  :    (TRUE)    (FALSE). 
 fInitialState    :  
(TRUE)   (FALSE).       , 
CreateEvent   ,    
.          : 1) 
 CreateEvent     IpszEventName; 2)  
; 3)  DuplicateHandle;  4)  OpenEvent   
  IpszEventName ,   ,     
   CreateEvent.     
OpenEvent HANDLE OpenEvent(DWORD fdwAccess, BOOL finherit, LPTSTR IpszName); 
            CloseHandle. 

        

            
  WaitForSingleQbject  WaitForMultipleObjects.   
-,       ,    
,        .  
 ,   ,    ,  , 
          . 
          ,  
       ,        
  . 
             .  
    ,    .  
  ,       
  .      ,   
      . ,    
      .     ,  
   .      -. 
,    ,   

    274 ______________________________Windows   

      .      
,   ,   , , ,  
,     . .      ,  
      :         
.     ,    . 
    ,          
  .          
 .         
 ,       . 
         SetEvent: 

    BOOL SetEvent(HANDLE hEvent); 

             
  .    ,   TRUE. 
         ,  
-    (. . )   , : 

    BOOL ResetEvent(HANOLE hEvent); 

              
 .    ,   TRUE. ( 
 ,        .) 
       ,  ,      
  ,   ResetEvent     ,  
  ,    SetEvent. 
    ,    .  ,    , ,  
   ?  ,      
       . ,    
 -     .    
      ,     
  ;  ,    ,  
  WaitForMultipleObjects   ,   
     . 
           SetEvent  
       ResetEvent,  Win32 
  ,     
 : 

    BOOL PulseEvent(HANDLE hEvent); 

        PulseEvent     
.    ,  TRUE. 

    -    

             ,  
        / 
.    ? :     
     . -  () 
  ,  -  ()    
 .       ,   
   : 
    1.    -     ,   
  . 
    2.    -     ,    
  . 
    3.     -    ,   
   . 

    __________________________ 10.   275 

    4.     -    ,   
  . 
          . ,    5 
 :     ,   . 
        1  ,  ,  ,   
   , ,   3457.   
       ,   , 
   .       . 
     2    ,      
.     , ,   
2543,      .      
  ,   .  3    
,    2.  ,  ,    
  : ,  ,  ,  ,    
   . 
    , ,  .   ,     
   ,       . 

    0',    .   :   ? 

     Bucket (BUCKET.EXE) (.   . 10-5)  
        .   
 5 ,     .   
         : 
   ,   .     
  5  (   ,    ), 
            
.           
BUCKET  -,   . 
       Bucket     : 
     ,   ,   ,   
 100 .   .  Bucket Writers   
    2 ,     
     ;  ,     
    .       
 ( ).      1  ,   
             
.          
(  0-60 ).  2    ,    
     3 . 

    276 _______________________________Windows   

          3 -.  
  -.     ( 0  60) 
    ,      
  . 
     ,     .  
-    ,    
   ,   -     
 .   ,  -    
    ,       
  ,  -    . 
      ,       ,    
       (. . 10-5)    
  ,    . 

    /\ 
            ,  
    ,    
.  ,         
         Bucket, 
    .    (     
)     .     
Bucket   ,         
,         . 


       SWMRG 

       Bucket   ,  ,  
            
  - .    / 
     ,    ,  
        ,  
   .  ,       
,             
 ,  .      SWMRG (    
swimerge);    single writer/multiple reader guard. 
     SWMRG     .    
       SWMRG.  SWMRG. (  
BUCKET  -,   ). ,  SWMRG   
  ,     
    / .  
  ,     3  : ,   
   .    ,   .   
,     . 
      ,       ,    
CRITICAL_SECTION. -,       SWMRG. 
     CRITICAL_SECTION,      
  (         ): 

    Sinclude "SWMRG.h" 
    SWMRG g_SWMRG:   //   SWMRG 

     SWMRG     ;    
           
    ( SWMRG.).  ,    
   CRITICAL_SECTION.                                         
     --
      -       
SWMRG,     SWMRGInitialize (  WinMain): 

    BOOL SWMRGInitialize(PSWMRG pSWMRG, LPCTSTR IpszName); 


    ___________________________ 10.   277 

         SWMRG,     
 .  SWMRGInitialize   
InitializeCriticalSection,   -    
:  SWMRG  ,      , 
   .      IpszName   
     (,  ,   
  ).       SWMRG   
,   IpszName  NULL.    SWMRG 
      . 
         ,     ( 
,  )     SWMRG,   
  SWMRGDelete: 

    void SWMRGDelete(PSWMRG pSWMRG); 

         SWMRGInitialize  SWMRGDelete  
      .   . 
   .  , -  , 
 EnterCriticalSection: 

    DWORD SWMRGWaitToWr-ite( PSWMRG pSWMRG, DWORD dwTimeout); 

    ,   - ,     
  SWMRG,      .     
   SWMRG   :     
  .  SWMRGWaitToWrite   
WAIT_OBJECT_0,  WAIT.TIMEOUT. 
     -        
(  WAIT_OBJECT_0),         
  SWMRGDoneWriting.     (  
)    : 

    void SWMRGDoneWriting(PSWMRG pSWMRG); 

        LeaveCriticalSection. 
          SWMRG   
-.  ,     
-.     -    , 
  SWMRGWaitToRead: 

    DWORD SWMRGWaitToRead(PSWMRG pSWMRG, DWORD dwTimeout); 

    ,   SWMRGWaitToWrite,         
.    ,   ,     . 
       ,     SWMRGDoneReading, 
  -      : 

    void SWMRGDoneReading(PSWMRG pSWMRG); 

    , -  ,      
  -. 
        ,      
SWMRG.       SWMRG: 

    typedef struct SingleWriterMultiReaderGuard { 
    
    //      ,   
    // ,    ,   - 
    // -""    
    HANDLE hMutexNoWriter; 
    
    //     ,  -"" 
    //      
    HANDLE hEventNoReaders; 

    . .  


    280 ______________________________Windows   


    hMutexNo Writer,  -,  SWMRGDoneReading,  
  ,       . 
      ,  SWMRGDoneReading  WaitForMultipkObjects  
WaitForSingleObject.   ,    
WaitForMultipleObjects,  hSemNumReaders.  :   
  ,      1  
.    SWMRGDoneReading  ,    
   . 
    ,      ,    
.    ,   Win32 ,   
   ,   .     
ReleaseSemaphore,    WaitForSingkObject    
hSemNumReaders,       1.  
ReleaseSemaphore     INumReaders, ,  
 ,     hEventNoReaders    
 SetEvent. 
     .     SWMRGDoneReading  
  (hMutexNoWriter)  ReleaseMutex.     
SWMRGWaitToRead,    ,    - 
 ,     . 

       Bucket 

       Bucket     
 SWMRG.    ,     
 ,   ,   SWMRGInitialize  
 IpszName  NULL.     SWMRG 
  DialogBox       . 
        ,     
WM_INITDIALOG.     Dlg_OnImtDialog  
    2 -  3 -. 
      ,     
   .    : , 
   ,    while,   
   g_lTerminate ,  1. (  
     0;      
 .) 
      while     Wii'132- Sleep, 
  ,    ,    : 

    Sleep(1000 * GetDlgItemInt(g_hwndDlg, nNumID, NULL, FALSE)); 

     Sleep    (  ), 
        . , 
-  SWMRGWaitToWrite,  -  
SWMRGWaitToRead.    SWMRGWaitToWrite - , 
        .     
 Bucket_AlterContents    . 
        SWMRGWaitToRead - ,   
    ,   -  
  .     Bucket_DumpToLB,  
 (  )       
   . 
       , -  - 
  SWMRGDoneWriting  SWMRGDoneReading (    
),  

    _________________________ 10.   281 

               
    while. 
       ,    ?   
  ,   ,  
 ,    DiahgBox   
WinMain     : 

    InterlockedIncrernent((PLONG) &g_lTerminate); 

         g_lTerminate  0  1.  
    ,     ,  
     :  .  
Interlockedlncrement        LONG, 
     .  ,   , 
    g_lTerminate,  
,  Interlockedlncrement     
. (   Interlockedlncrement .    .) 
       g_lTerminate  ,  
(  )  .      
,     - .    
,      . ,  
WaitForMultipleObjects,      . ( : 
          
Dlg_OnInitDialog.)    , WaitForMultipleObjects  
,    5   CloseHandle,   
   . 
    , ,      SWMRGDelete,  
     hMutexNoWriter, 
hEventNoReaders  hSemNumReaders      . 
         Bucket,    
PERFMON.EXE,     Windows NT,     
 "' .  BUCKET.EXE,    
PERFMON.EXE,      Edit ()  Add To Chart 
(  );       : 

    ____________________________________________1 

          Object ()   Process (), 
  Instance ()  Bucket,    Counter ()  Thread 
Count ( ).    Add ().  
,    PerfMon    , 
   Bucket.   ,     : 

    282 _______________________________Windows   

       ,    Bucket   
 6 .  -        
.      g_lTerminate  1; 
     3   .   
       while,   
g_lTerminate  .  ,       
.    5 ,     
 .           
  . 
     , PERFMON.EXE    ,   
 ,   ! 

    BUCKET.C 
    ; Bucket. : Copyright  1995-1997,   (Jeffrey Richter) 
    #*************+*************************+*************************************/ 
    #include "..\CmnHdr.H"           /* .   */ 
    Sinclude <windows.h> 
    Itinclude <windowsx.h> 
    #include <tchar.h> 
    ftinclude <stdio.h>               //  sprintf 
    ffinclude <stdlib.h>              //     
    ffinclude <process.h>             //  _beginthreadex 
    Sinclude "Resource.H" 
    #include "SWMRG.H" 
    
    //     " / " 
    SWMRG g_SWMRG; 

    . . . 

    . 10-5.   Bucket 


    _______________________ 10.   283 


    . -5 () 

    I/   ,      
    HANDLE g_hThreads[5]; 
    
    // ,      
    // (volatile, ..   ) 
    long volatile g_lTerminate = 0; 
    
    //     
    HWND g_hwndDlg = NULL; 
    
    lllllllllllllllllllllll/lllllllllllllli/ll/'llil'ln/llli/iiil/liiii In // 
IIIIIIIIIIIIIIIII       ////////////////// 
    ///////////////////////////////////////////////////////////////////////////// 
    
    //     ( ) 
    typedef enum { 
    BC_FIRSTBALLCLR, 
    // BC_NULL      
    BCJIULL = BC_FIRSTBALLCLR, 
    BC_BLACK, 
    BC_RED, 
    BC_GREEN, 
    BC_BLUE, 
    BCJriHITE, 
    BC_YELLOW, 
    BC_ORANGE, 
    BC_CYAN, 
    BC_GRAY, 
    
    BC_LASTBALLCLR = BC_GRAY 
    } BALLCOLOR: 
    
    //     ( ) 
    const TCHAR *szBallColors[] = { 
    NULL, 
    __TEXT("Black"), 
    __TEXT("Red"), 
    __TEXT("Green"), 
    __TEXT("Blue"), 
    __TEXT("White"), 
    __TEXT("Yellow"), 
    __TEXT("Orange"), 
    __TEXT("Cyan"), 
    __TEXT("Gray") 
    }; 
    
    
    //      
    Sdefine MAX_BALLS    100 
    
    //   .   volatile, ..   
    //  . 


    284 ______________________________Windows   


    . 10-5 () 

    BALLCOLOR volatile g_Bucket[MAX_BALLS] = { BC_NULL }; 
    
    /////////////////////////////////////////////////////////////////////////////// 
    void BLicket_AlterContents (void) { 
    
    // /""     ( ) 
    g_Bucket[rand() % MAX_BALLS] = (BALLCOLOR) (rand() % 10); 
    
    /////////////////////////////////////////////////////////////////////////////// 
    vuia Bucket_DumpToLB (HWND hwridLB) { 
    int nBallNurri; 
    int nBaUColor[BC_LASTBALLCLR - BC_FIRSTBALLCLR + 1] = { 0 }: 
    BALLCOLOR BallColor; 
    TCHAR szBuf[50]; 
    
    // ,       
    for (nBallNum = 0; nBallNum < MAX_BALLS; nBallNu(ii++) { 
    //      nBallNum 
    BallGolor = g_Bucket[nBallNum]: 
    
    //      
    111[111]++; 
    } 
    
    //    
    ListBox_ResetContent(hwndLB); 
    
    //    
    BallColor = BC_FIRSTBALLCLR; 
    for (; BallColor <= BC_LASTBALLCLR; 111++) { 
    if (szBallColors[BallColor] != NULL) { 
    
    _stpnntf(szBuf, __TEXT("%s: %*s%2d"), szBallColors[BallColor], 
    7 - lstrlen(szBallColors[BallColor]), __TEXT(" "), 
    nBallColor[BallColor]); 
    } else { 
    _stpnntf(szBuf, __TEXT( "Total: %2d"). 
    MAX_BALLS - nBaUColor[BallGolor]); 
    i 
     
    ListBox_AddString(hwndLB, szBuf): 
    i / 
    1111111111111111111111111111111111111111111111111111111111111111111111111111111 

    ________________________ 10.   285 


    . 10-5 () 
    
    DWORD WINAPI Writer (LPVOID IpvParam) { 
    int nWriterNum = (int) IpvParam, nNumID; 
    
    switch (nWriterNum) { 
    case 1: 
    nNumID = IDC_WRITE1NUM; 
    break; 
    case 2: 
    nNumID = IDC_WRITE2NUM; 
    break; 
    default: 
    
    nNumID = 0; //      
    break; 
    
    //     ,     
    while (!g_lTerminate) { 
    
    //       
    Sleep(1000 * GetDlgItemInt(g_hwndDlg, nNumID, NULL, FALSE)); 
    
    // ,     (   "", 
    //  "") 
    SWMRGWaitToWrite(&g_SWMRQ. INFINITE); 
    
    //     ( ) 
    Bucket_AlterContents(); 
    
    //   ,    
    SWMRGDoneWriting(&g_SWMRG); 
    1 ( 
    return(O); 
    i i 
    iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii/iii/iiiiiiiiiiiiiiiiiiiiiiiiii 
    DWORD WINAPI Reader (LPVOID IpvParam) { 
    int nReaderNum = (int) IpvParam. nNumID ^ 0; 
    HWND hwndLB = NULL: 
    
    //     ,   , 
    //      (),   
    //   "" 
    switch (nReaderNum) { 
    case 1: 
    nNumID = IDC_READ1NUM; 
    hwndLB = GetDlgItem(g_hwndDIg, IDC_READ1LIST); 
    break; 

    286 _______________________________Windows   


    . 10-5 () 

    case 2: 
    nNumID = IDC_READ2NUM; 
    hwndLB = GetDlgItem(g_hwnd01g, IDC_READ2LIST); 
    break; 
    case 3: 
    nNumID = IDC_READ3NUM; 
    hwndLB = GetDlgItem(g_hwndDlg, IDC_READ3LIST); 
    break: 
    default: 
    
    nNumID = 0; //      
    hwndLB = NULL; 
    break; 
    
    //     ,     
    while (! g_lTernnnate) { 
    
    //       
    Sleep(1000 * GetDlgItemInt(g_hwndDlg, nNumID. NULL, FALSE)); 
    
    
    // ,     (  "") 
    SWMRGWaitToRead(&g_SWMRG, INFINITE): 
    
    
    //     ( ) 
    Bucket_DumpToLB(hwndLB); 
    
    
    //   ,    
    
    
    SWMRGDoneReading(&g_SWMRG); 
    
    
    } 
    return(O); 
    
    
    BOOL Dlg_OnInitDialog (MHO hwnd, HWND hwndFocus, LPARAM IParam) { 
    
    
    DWORD dwTrireadID: 
    
    
    int x; 
    
    
    //      
    ch8ETDLGICONS(hwnd, IDI_BUCKET, IDI_BUCKET); 
    
    
    //       ,  
    //       .     
    //  . 
    g_hwndDlg = hwnd; 
    
    . . . 

    __________________________ 10.   287 


    . 10-5 () 

    II  ,    
    //  -" 
    ScrollBar_SetRange(GetDlgItern(hwnd, IDC_WRITE1SCRL), 0, 60. FALSE); 
    ScrollBar_SetPos(GetDlgItem(hwnd, IDCWRITE1SCRL), 1, TRUE); 
    SetDlgItemInt(hwnd, IOC_WRITE1NUM, 1, FALSE); 
    ScrollBar_SetRange(GetDlgItem(hwnd, IDCJOTTE2SCRL), 0, 60, FALSE); 
    ScrollBar_SetPos(GetDlgItem(hwnd, IDCJi)RITE2SCRL), 3, TRUE); 
    SetDlgItemInt(hwnd, IDC_WRITE2NUM, 3, FALSE); 
    //  ,    
    //  -"" 
    ScrollBar_SetRange(GetDlgItem(hwnd, IDC_READ1SCRL), 0, 60, FALSE); 
    ScrollBar_SetPos(GetDlgItem(hwnd, IDC_READ1SCRL), 2, TRUE); 
    SetDlgItemInt(hwnd, IDC_REA01NUM, 2. FALSE); 
    ScrollBar_SetRange(GetDlgItem(hwnd, IDC_READ2SCRL), 0, 60, FALSE): 
    ScrollBar_SetPos(GetDlgItem(hwnd, IDC_READ2SCRL), 4, TRUE); 
    SetDlgItemInt(hwnd, IDC_READ2NUM, 4, FALSE); 
    ScrollBar_SetRange(GetDlgItem(hwnd, IDC_READ3SCRL), 0, 60, FALSE); 
    Scr-ollBar_SetPos(GetDlgItem(hwnd, IDC_READ3SCRL), 7, TRUE); 
    SetDlgItemInt(hwnd, IDC_READ3NUM, 7, FALSE); 
    //  2 -""  3 -"". 
    // ":         t . 
    //   . 
    for ( = 0;  <= 1: ++) { 
    
    g_hThreads[x] = chBEGINTHREADEX(NULL, 0, Writer, 
    (LPVOID) ( + 1), 0, &dwThreadID); 
    } 
    tor (x = 2; x <= 4; x++) { 
    g_hThreads[x] = chBEGINTHREADEX(NULL, 0, Reader, 
    (LPVOID) (x - 1), 0, &dwThreadID); 
    \ 
    i 
    return(TRUE); 
    } 
    ///'//////////////////////////////////////////////////V///'///'///11///-1/,,'/1,1"/,,1.1/ 
    void Dlg_OnHScroll (HWND hwnd, HWND hwndCtI, UINT code, int pos) { 
    int posCrnt, posMin, posMax; 
    posCrnt = ScrollBar_GetPos(hwndCtl); 
    ScrollBar_GetRange(hwndCtl, &posMin, &posMax); 

    . . . 


    288 _______________________________Windows   


    . 10-5 () 

    switch (code) { 
    case SB_LINELEFT: 
    posCrnt--; 
    break; 
    case SB_LINERIGHT: 
    posCrnt++; 
    break: 
    case SB_PAGELEFT: 
    posCrnt -= 10; 
    break; 
    case SB_PAGERIGHT: 
    posCrnt += 10; 
    break: 
    case SB_THUMBTRACK; 
    posCrnt = pos; 
    break: 
    case SB_LEFT: 
    posCrnt = 0; 
    break; 
    case SB_RIGHT: 
    posCrnt = posMax; 
    break; 
    
    if (posCrnt < 0) 
    posCrnt = 0; 
    
    
    if (posGrnt > posMax) 
    posCrnt = posMax; 
    
    ScrollBar_SetPos(hwndGtl, posCrnt, TRUE); 
    SetDlgItemInt(hwnd, GetDlgCtrlID(hwndCtl) - 1, posCrnt, FALSE); 
    } 
    
    /////////////////////////////////////////////////////////////////////////////// 
    void Dlg_OnVScroll (HWND hwnd, HWND hwndCtI, UINT code, int pos) { 
    int posGrnt, posMin, posMax; 
    posCrnt = ScrollBar_GetPos(hwndCtl); 
    ScrollBar_GetRange(hwndCtl. &posMln, &posMax); 


    _________________________ 10.   289 


    . 10-5 () 
    
    switch (code) < 
    case SB_LINEUP: 
    posCrnt--; 
    break; 
    case SB_LINEDOWN: 
    posCrnt++; 
    break; 
    case SB_PAGEUP: 
    posCrnt -= 10; 
    break; 
    
    case SB_PAGEDOWN 
    posCrnt += 10: 
    break; 
    case SB_THUMBTRACK: 
    posCrnt = pos; 
    break; 
    case SB_TOP: 
    posCrnt = 0; 
    break; 
    case SB_BOTTOM: 
    posCrnt = posMax; 
    break; 
    
    if (posCrnt < 0) 
    posCrnt = 0; 
    
    if (posCrnt > posMax) 
    posCrnt = posMax; 
    ScrollBar_SetPos(hwndGtl, posCrnt, TRUE); 
    SetDlgItemInt(hwnd, GetDlgCtrlID(hwndCtl) - 1, posCrnt, FALSE); 
    
    void Dlg_OnGoirimand (HWND hwnd, int id, HWND hwndCtI, UINT codeNotify) { 
    switch (id) { 
    case IDCANCEL: 
    EndDialog(hwnd, id); 
    break; 
    } 


    290 ______________________________Windows   


    . 10-5 () 
    
    BOOL CALLBACK Dlg_Proc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM 
IParam) { 
    switch (uMsg) { 
    chHANDLE_DLGMSG(hwnd, WM_INITDIALOG, Dlg_OnInitDialog); 
    chHANDLE_DLGMSG(hwnd, WM_COMMAND, Dlg_OnCommand); 
    chHANDLE_DLQMSG(hwnd, WM_HSCROLL, Dlg_OnHScroll); 
    chHANDLE_DLGMSG(hwnd, WM_VSCROLL, Dlg_OnVScroll): 
    return(FALSE); 
    i 
    !///i/////li////////////l///l//lli/i/l//!i/i:/i!Hi/:i!i//i!ii/, ,',. i,, 
    int WINAPI _tWinMain (HINSTANCE hinstExe, 
    HINSTANCE hins'tPrev, LPTSTR pszCmdLine, int nCnidShow) { 
    int x: 
    chWARNIFUNICODEUNDERWIN95(); 
    
    //   SWMRG.     , 
    //       . 
    SWMRGInitialize(&g_SWMRG, NULL); 
    
    //     
    DialogBox(hinstExe, MAKEINTRESOURCE(IDD_BUCKET), NULL, Dlg_Proc): 
    //    ,  : 
    
    // 1.  ,   . 
    Inter locked Increment((PLONG) &g_lTerminate); 
    
    // 2,    .     - , 
    // ..  , ,       
    //   g_lTerminate. 
    WaitForMultipleObjects(chDIMOF(g_hThreads), g_hThreads, TRUE, INFINITE): 
    
    // 3.    . 
    for (x = 0;  < chDIMOF(g_hThreads); x++) 
    CloseHandle(g_hThreads[x]); 
    
    // 4.    SWMRG,   , 
    //    ,        
    //  . 
    SWMRGDelete(&g_SWMRG); 
    return(O); 
    } 
    //////////////////////////////////   ///////////////////////////////// 

    . . i'fnp. 

    ________________________ 10.   291 


    , 10-5 () 

    SWMRG.C 
    : SWMRG.C 
    : Copyright  1995-1997,   (Jeffrey Richter) 
    fflnclude "..\CmnHdr.H"           /* .   */ 
    ftinclude <windows.h> 
    #include <string.h> 
    Sinclude <tchar.h> 
    ttinclude "SWMRG.H"               //   
    lllllllllllllll/ll//^!/i!/!l/!^!/^/lllllllllllllllll/l^^!^!i':!!::!:l::!:'!!' 
    static LPCTSTR ConstructObjName ( 
    LPCTSTR IpszPrefix, LPCTSTR IpszSuffix, 
    LPTSTR IpszFullName, size_t cbFullName, PBOOL fOk) { 
    *f0k = TRUE; // ,    
    
    if (IpszSuffix == NULL) 
    return(NULL); 
    if ((_tcslen(lpszPrefix) + _tcslen(lpszSuffix)) >= cbFullName) { 
    //    ,    
    *f0k = FALSE; 
    return(NULL); 
    } 
    _tcscpy(lpszFullNarne, IpszPrefix); 
    _tcscat(IpszFullName, IpszSuffix); 
    return(IpszFullName); 
    } 
    //,1'/,'/// /l/lllllllll/ill /:!! /Ilii i/ i/!i/i /in'i/i ! /i/ 'lil/i^i 
    
    BOOL SWMRGInitiallze(PSWMRG pSWMRG, LPCTSTR IpszName) { 
    TCHAR szFullObjName[100]; 
    LPCTSTR IpszObjName: 
    BOOL fOk; 
    
    5|,     //     NULL,    
    //  ,     
    pSWMRG->hMutexNoWrlter = NULL; 
    pSWMRG->hEventNoReaders = NULL; 
    pSWMRG->hSernNumReaders = NULL: 
    // -     ,  
    //   ,   ,    - 
    
    . . . 


    292 _______________________________. Windows   


    . 10-5 () 
    
    II -"".       . 
    IpszObjName = ConstructObjName(__TEXT("SWMRGMutexNoWriter"), IpszName, 
    szFullObjName, chDIMOF(szFullObjName), &f0k); 
    if (fOk) 
    pSWMRG->hMutexNoWriter = CreateMutex(NULL, FALSE, IpszObjName); 
    //   "   ";  ,  
    //     -"".  -"" 
    //    . 
    IpszObjName = ConstructObjName(__TEXT("SWMRGEventNoReaders"), IpszName, 
    szFullObjName, chDIMOF(szFullObjName), &f0k); 
    if (fOk) 
    pSWMRG->hEventNoReaders = CreateEvent(NULL, TRUE, TRUE, IpszObjName); 
    //  ,    . 
    //  .  -""    . 
    IpszObjName = ConstructObjName(__TEXT("SWMRGSemNumReaders"), IpszName, 
    szFullObjName. chDIMOF(szFullObjName), &f0k); 
    if (fOk) 
    pSWMRG->hSemNumReaders = CreateSemaphore(NULL, 0, Ox7FFFFFFF, IpszObjName); 
    if ((NULL == pSWMRG->hMutexNoWriter) :; (NULL == pSWMRG->hEventNoReaders) ;: 
    (NULL == pSWMRG->hSemNumReaders)) < 
    //      , 
    //         
    SWMRGDelete(pSWMRG); 
    fOk = FALSE; 
    } else { 
    fOk = TRUE; 
    } 
    //   ,  TRUE;    - FALSE 
    return(fOk); 
     
    /Illlllllllllll/l/l/llllllllllllll/lllll/llllllll/llllllllllflllllllllll/llllll 
    void SWMRGDelete(PSWMRG pSWMRG) { 
    //       
    if (NULL != p8WMRG->hMutexNoWriter) 
    CloseHandle(pSWMRG->hMutexNoWriter); 
    
    
    if (NULL != pSWMRG->hEventNoReaders) 
    CloseHandle(pSWMRG->hEventNoReaders); 
    
    
    if (NULL != pSWMRG->hSemNumReaders) 
    CloseHandle(pSWMRG->hSemNumReaders); 
    
    
    } 
    
    //IIIIIIIIIIIIIIIIIH/  /11/1111///1/11///111/1/1 //111/1///111/I IIIIIIIIH ;//; 


    _________________________ 10.    293 


    . 10-5 () 
    
    DWORD SWMRGWaitToWrite(PSWMRG pSWMRG, DWORD dwTimeout) { 
    DWORD dw; 
    
    HANDLE aHandles[2]; 
    //      : 
    // 1.           
    //    -"". 
    // 2.    . 
    aHandles[0] = pSWMRQ->hMutexNoWriter; 
    aHandles[1] = pSWMRG->hEventNoReaders; 
    dw = WaitForMultipleObjects(2, aHandles, TRUE, dwTimeout); 
    if (dw != WAITJ'IMEOUT) { 
    
    //       . 
    //   ,   . 
    //      . 
    return(dw); 
    } 
    Ill/lill/lll/lllli/llll/llllllli/lll/lllllllllllllllllllll/llllllllllllllllllll 
    void SWMRGDoneWriting(PSWMRG pSWMRG) { 
    
    //  -"",   ,  
    //  SWMRGWaitToWrite.   ,    
    //   , ..     -. 
    //      SWMRG. 
    ReleaseMutex(pSWMRG->hMutexNoWriter); 
    } 
    ll/lllllllllllll/lllllllllllil/llll/lllll//l//!/i//i///lil/liil/ll!lll!!il/!ll' 
    
    DWORD SWMRGWaitToRead(PSWMRG pSWMRG, DWORD dwTimeout) ( 
    DWORD dw: 
    LONG IPreviousCount; 
    //  ,      
    //       
    dw = WaitForSingleObject(pSWMRG->hMutexNoWriter, dwTimeout); 
    if (dw != WAIT_TIMEOUT) { 
    
    //        . 
    //    -"". 
    Release8emaphore(pSWMRG->hSemNumReaders, 1, &lPreviousCount); 
    if (IPreviousCount == 0) { 
    //    -"",  
    //  - 
    ResetEvent(pSWMRG->hEventNoReaders); 
    ) 


    294 _____________________________ Windows   


    . 10-5 () 
    
    II     
    //   SWMRG 
    ReleaseMutex(pSWMRG->hMutexNoWriter); 
    } 
    return(dw); 
    
    void SWMRGDoneReading (PSWMRG pSWMRG) { 
    HANDLE aHandles[2]; 
    LONG INumReaders; 
    
    //   ,   ,    
    //      -""  1 
    aHandles[0] = p8WMRG->hMutexNoWriter; 
    
    
    aHandles[1] = pSWMRG->hSemNumReaders; 
    
    
    WaitForMultipleObjects(2, aHandles. TRUE, INFINITE): 
    
    
    //    "",   
    //       
    // WaitForSingleObject 
    ReleaseSemaphore(pSWMRG->hSemNumReaders, 1, &lNumReaders); 
    
    
    WaitForSingleObject(pSWMRG->hSemNumReaders, INFINITE); 
    
    
    if (INumReaders == 0) { 
    
    
    //    -"",  
    //  - 
    
    
    SetEvent(pSWMRG->hEventNoReaders); 
    
    
    i 
    { 
    
    
    II     
    //   SWMRG 
    ReleaseMutex(pSWMRG->hMutexNoWriter); 
    
    
    } 
    
    
////////////////////// ///////////////
    
    
    SWMRG. 
    
    
    /,,,,.*,**,**,*,*.. .^,,^.,^,^.^^....*,*.*,^,.^^^ 
    
    : SWMRG.   
    : Copyright  1995-1997,   (Jeffrey Richter) 
    
    
    //   SWMRG (single-writer/multiple-reader guard) 
    typedef struct SingleWriterMultiReaderGuard { 
    
    
    . . . 

    __________________________ 10.    295 


    . 10-5 () 
    
    II      ,  
    //   ,    : 
    
    
    //      -"" 
    HANDLE hMutexNoWriter; 
    
    
    //     ,     
    //   -"" 
    HANDLE hEventNoReaders; 
    
    
    //    ,   
    // ;      , 
    //    ,    
    HANDLE hSemNumReaders; 
    
    
    } SWMRG, *PSWMRG; 
    
    
    11 llllllll/11111111/l, l iiiHii:/Hii:/:/il, //7/'////////7/,7/7///.,1, /,...,,,, 
    
    
    //   SWMRG (   ,  
    //    -  ). 
    //    ,       
    // ,   (IpszName)   . 
    //    NULL,       
    //  . 
    BOOL  SWMRGInitialize (PSWMRG pSWMRG, LPCTSTR IpszName); 
    
    
    //   ,    SWMRG. 
    //   ,      - 
    //    , 
    void  SWMRGDelete (PSWMRG pSWMRG); 
    
    
    // -""   ,  ,   
    
    //    -    
    
    
    DWORD SWMRGWaitToWrite (PSWMRG pSWMRG, DWORD dwTimeout); 
    
    
    // -""   ,    
    
    
    //   ,       -    
    
    void  SWMRGDoneWnting (PSWMRG pSWMRG); 
    
    
    // -""   ,  ,   
    
    
    //       
    
    
    DWORD SWMRGWaitToRead  (PSWMRG pSWMRG, DWORD dwTimeout); 
    
    
    // -""   ,    
    
    
    //   ,       -    
    
    
    void  SWMRGDoneReading (PSWMRG pSWMRG); 
    
/////////////////////////  1111111111! 111111111111 H 11111111 

    296 ______________________________Windows   


       

             ,  
    .    SetEvent,   
,     ,     , 
   .        
     .   
       - 
   .  -   .   , 
      ,    
 . ,      ,     
 .    :     
 ,   ,    () . 
      ,      ,   
SetEvent, ResetEvent  PulseEvent. ResetEvent   ,  
    WaitEorSingleObjectn 
^^^^  (   )  
.                                ~"' 
    PulseEvent        ,    
   :  ,   
          .  
      :     
          
  ,         
       . 

    - DocStats 

     DocStats (DOCSTATS.EXE) (.   . 10-6)  
   .        
    DOCSTATS  -,   . 
  DocStats     : 
         - ,  
   (  )       
,   Browse ().  DocStats   
ANSI-        Unicode-. 
    DocStats     ,  ,   
  .       ,  ,   
   . 
        Calculate Document Statistics ( 
),   3        
  (,  ~).    
,       ,  
.       

     10.   297 

        1024 .     ,  
     ,     
       . 
             
,      1024   
.        ,     
,  ,      . ,  
    ,    ,  
 ,    ,     . 
    ""    DocStats ,    
     .     
  6      2    .  
         ,  
           . 
      g_hEventsDataReady.   
      ,   ,  
     . 
           ,    
  ,    ,     
 ,     ,   
     .     
  g_hEventsProddle.        
 ,   ,    . 
        3  .     
 (  ).      
hThreads.              
   ,   .  
          
 ,     .    
   WaitForSingleObject,    
    g_hEventsDataReady. 
          ,     
      .     
 ,      g_hEventsProddle, 
,          .  
  1024         
,   .       SetEvent   
   ,      g_hEventsDataReady. 
        ,     
   .        
,      ,  
 ,      .      
     .  , ,   
,     . 
       ,      , 
       .   
   ,   ,     
    .  - !  - 
     ,      
  (      ).   
  ,        
.   3  ,    
           . 

    298 ___________________________Windows   

      ,     SetEventfins 
 ,      
g_hEventsProc[dle.      ,  
 .          
 WaitForMultipkObjects (      ).  
            . 
     WaitForMultipleObjects     , 
 g_hEventsProcIdle     , 
,          
. (        g_hEventsDataReady.) 
           g_hEventsProcIdle  
 ?  ,     
 ,         . 
      ,        ,  
g_hEventsDataReady  ,        . 
            
g_hEventsProddle, ,        , 
     .     ,   
             ! 
    ,  ,  ,    
       ,   
        
:    ,     .   
          . 
           ,  
      . 
          DocStats,    
 .    20   ,  
 . 
            .  ,  
      ,    
 .      return    
         .   
  WaitForMultipleObjects,      
,      ,   ,   
 hThreads. 
         ,  GetExitCodeThread, 
    .    CloseHandle  
 6   3 ,    . , , 
    . 
    DOCSTATS.C 
    ; DocStats. 
    : Copyright  1995-1997,   (Jeffrey Richter) 
    #include "..\CmnHdr,H"           /* .   */ 
    Sinclude <windows.h> 
    include <windowsx.h> 
    ftinclude <tchar.h> 
    Sinclude <stdio.h>               //  sprintf 

    . . . 

    . 10-6.   DocStats 

    _________________________ 10.   299 


    . 10-6 () 

    include <string. h> 
    include <process.h>                //  _beginthreadex 
    ftinclude "Resource.H" 
    ////////////////////////////////1/////////////////////////////.'/' / /  
    typedef enum { 
    STAT_FIRST = 0, 
    STAT_LETTERS = STAT_FIRST, 
    STAT_WORDS, 
    STAT_LINES, 
    STAT_LAST = STAT_LINES 
    } STATTYPE: 
    HANDLE g_hEventsDataReady[STAT_LAST - STAT_FIRST +1]: 
    HANDLE g_hEventsProcIdle[STAT_LAST - STAT_FIRST +1]; 
    BYTE g_bFile8uf[1024]; 
    DWORD g_dwNumBytes!nBuf; 
    
    //   
    WORD WINAPI StatThreadFunc(LPVOID IpvParam); 
    ///////////////////////////////
    BOOL DocStats(LPCTSTR pszPathname, PDWORD pdwNumLetters, 
    PDWORD pdwNumWords, PDWORD pdwNumLines) { 
    HANDLE hThreads[STAT_LAST - STAT_FIRST + 1]; 
    HANDLE hFile; 
    DWORD dwThreadID; 
    STATTYPE StatType; 
    *pdwNumLetters = 0; 
    *pdwNumWords = 0; 
    *pdwNumLines = 0; 
    
    //     
    hFile = CreateFile(pszPathname, GENERIC_READ, 0, 
    NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL): 
    if (hFile == INVALID_HANDLE_VALUE) { 
    //     
    chMB(__TEXT("File could not be opened.")); 
    return(FALSE); 
    } 
    
    for (StatType = STAT_FIRST; StatType < STAT_LAST + 1; StatType++) { 
    // ,      
    g_hEventsDataReady[StatType] = CreateEvent(NULL, FALSE, FALSE, NULL): 
    
    
    g_hEventsProcIdle[StatType] = CreateEvent(NULL. FALSE, TRUE. NULL): 
    
    i. . . 

    300 _______________________________Windows   


    . 10-6 () 
    

    //   ,      
    // -. 
    
    
    hThreads[StatType] = chBEGINTHREADEX(NULL, , 
    StatThreadFunc, (PVOID) StatType, 0, &dwThreadIO); 
    
    do { 
    
    
    // .      
    WaitForMultipleObjects(STAT_LAST - STAT_FIRST + 1, 
    9_hEventsProcIdle, TRUE, INFINITE); 
    
    
    //       
    ReadFile(hFlle, g_bFileBuf, chDIMOF(g_bFileBuf), 
    &g_dwNufflBytesInBuT, NULL): 
    
    
    //  "",      
    for (StatType = STAT_FIRST; StatType < STAT_LAST + 1; StatType++) { 
    
    
    SetEvent(g_hEventsDataReady[StatType]); 
    
    
    } while (g_dwNumBytesInBuf != 0); 
    
    
    //     ;     
    CloseHandle(hFile): 
    
    
    //  ""    
    WaitForMultipleObjects(STAT_LAST - STAT_FIRST + 1, hThreads, TRUE, INFINITE); 
    
    
    //      
    GetExltCodeThread(hThreads[STAT_LETTERS], pdwNumLetters); 
    
    
    GetExitCodeThread(hThreads[STAT_WORDS], pdwNumWords): 
    
    
    GetExitCodeThread(hThreads[STAT_LINES], pdwNumLines); 
    
    
    //      
    for (StatType = STAT_FIRST; StatType < STAT_LAST + 1; StatType++) { 
    
    
    CloseHandle(hThreads[StatType]); 
    
    
    CloseHandle(g_hEventsDataRead[StatType]): 
    
    
    CloseHandle(g_hEventsProcIdle[StatType]); 
    
    
    } 
    
    
    return(TRUE); 
    
    
    } 
    
    
    ////////////////////////
    
    DWORD WINAPI StatThreadFunc(LPVOID IpvParam) { 
    STATTYPE StatType = (STATTYPE) IpvParam; 
    
    
    DWORD dwNumBytesInBuf, dwByteIndex, dwNumStat = 0; 
    
    
    BYTE bByte; 
    
    
    BOOL fInWord = FALSE. fIslriordSep; 
    
    . . . 

    __________________________ 10.   301 


    . 10-6 () 
    1! ()   ( 
    
    // ,     
    WaitForSingleObject(g_hEventsDataReady[StatType], INFINITE); 
    
    
    dwNumBytesInBuf = g_dwNumBytesInBuf; 
    
    
    dwByteIndex = 0: 
    
    
    for (: dwByteIndex < dwNumBytesInBuf; dwByte!ndex++) { 
    
    
    bByte = g_bFileBuf[dwByte!ndex]; 
    
    
    //      ANSI-  
    //  ,       ANSI  Unicode 
    switch (StatType) { 
    case STAT_LETTERS: 
    
    
    if (IsCharAlphaA(bByte)) 
    dwNumStat++; 
    
    
    break; 
    
    
    case STAT_WORDS: 
    
    
    fIsWordSep = (strchr(" \t\n\r", bByte) != NULL); 
    
    
    if (!fInWord && !fIsWordSep) { 
    dwNumStat++; 
    
    
    fInWord = TRUE; 
    
    
    } else { 
    
    
    if (fInWord && fIsWordSep) 
    fInWord = FALSE: 
    
    
    break; 
    
    
    case STAT_LINES: 
    
    
    if ('\n' == bByte) 
    dwNumStat++; 
    
    
    break: 
    
    
    i 
    i 
    
    
    II  ; ,    
    SetEvent(g_hEventsProddle[ StatType]); 
    
    
    } while (dwNumBytesInBuf > 0); 
    
    
    return(dwNumStat); 
    
    
    } 
    
    ////////////////////////
    BOOL Dlg_0nlnit0ialog (HWND hwnd, HWND hwndFocus, LPARAM IPararn) {     
    
    //      
    chSETDLGICONS(hwnd, IDI_DOCSTATS, IDI_DOCSTATS); 
    
    . . . 

    302 _______________________________Windows   


    . 10-6 () 

    II   ,     
    //   
    EnableWindow(GetDlgItem(hwnd, IDC_DODOCSTATS), FALSE); 
    return(TRUE); 
    } 
    void Dlg_OnCommand (HWNO hwnd, int id, HWND hwndCtI, UINT codeNotify) { 
    TCHAR szPathname[_MAX_PATH]; 
    OPENFILENAME ofn; 
    DWORD dwNumLetters, dwNumWords, dwNurnLines: 
    switch (id) { 
    
    case IDC_FILENAME: 
    
    
    EnableWindow(GetDlgItem(hwnd, IDC_DODOCSTATS), 
    Edit_GetTextLength(hwndCtl) > 0); 
    
    
    break; 
    
    
    case IDC_FILESELECT: 
    
    
    chINITSTRUCT(ofn, TRUE); 
    
    
    ofn.hwndOwner = hwnd; 
    
    
    ofn.IpstrFile = szPathname; 
    
    
    ofn,lpstrFile[0] = 0: 
    
    
    orn.nMaxFile = chDIMOF(szPathname); 
    
    
    ofn.IpstrTitle = __TEXT("Select file for reversing"); 
    
    
    Ofn,Flags = OFN_EXPLORER : OFN_FILEMUSTEXIST; 
    
    
    GetOpenFileName(&ofn); 
    
    
    SetDlgItemText(hwnd, IDC_FILENAME, ofn,IpstrFile); 
    
    
    SetFocus(GetDlgItem(hwnd, IDC_DODOCSTATS)): 
    
    
    break; 
    
    
    case IDC_DODOGSTATS: 
    
    
    GetDlgItemText(hwnd, IDC_FILENAME, szPathname, chDIMOF(szPathname)); 
    
    
    if (DocStats(szPathname, &dwNumLetters, &dwNumWords, &dwNumLines) ) { 
    
    
    SetDlgItemInt(hwnd, IDC_NUMLETTERS, dwNumLetters, FALSE); 
    
    
    SetDlgItemInt(hwnd, IDC_NUMWORDS, dwNumWords, FALSE); 
    
    
    SetDlgItemInt(hwnd, IDC_NUMLINES, dwNumLines, FALSE): 
    
    
    i 
    
    
    break; 
    
    
    case IDCANCEL: 
    
    EndDialog(hwnd, id); 
    
    
    break; 
    
    
    / 
    
    
    ////////////////////

    . . en 1 

    ___________________________ 10.   303 
    . 10-6 () 
    
    BOOL CALLBACK Dlg_Proc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM 
IParam) { 
    switch (uMsg) { 
    
    
    chHANDLE_DLGMSG(hwnd, WM_INITDIALOG,  Dlg_OnInitDialog); 
    
    
    chHANDLE_DLGMSG(hwnd, WM_COMMAND, Dlg_OnCommand): 
    
    
    } 
    return(FALSE): 
    
    
    int WINAPI _tWinMain (HINSTANCE hinstExe, 
    
    
    HINSTANCE hinstPrev, LPTSTR pszCmdLine, int nCmdShow) { 
    
    
    ChWARNIFUNICODEUNDERWIN95(); 
    
    
    DialogBox(hinstExe, MAKEINTRESOURCE(IDDJ)OCSTATS), NULL, Dlg_Proc); 
    
    
    return(O); 
    
    
    } 
    
    
    //////////////////////////////////   I I I I I I / I I I I / / I 
    
    
      
    
      (waitable timers)   Windows NT 4.   
,         
/    .    , 
   Create WaitableTimer. 
    
    HANDLE CreateWaitableTimer-(LPSECURITY_ATTRIBUTES Ipsa, 
    BOOL bManualReset, LPCTSTR IpszTimerName); 

     Ipsa  IpszTimerName      
   .   bManualReset  TRUE,   
,   ,   ,   FALSE  
    (     ). 

    XWINDOWS/  Windows_95^     ,     
 .    ,   ,   Windows 
95    . 

    ,      (-) 
    ,  OpenWaitableTimer. 

    HANDLE OpenWaitableTimer(DWORD dwDesiredAccess, BOOL bInhentHandle, 
    LPCTSTR IpszTimerName); 
       ,      : 
    BOOL SetWaitableTimer(HANDLE hTimer, 
    const LARGE_INTEGER *pDueTime, LONG IPeriod, 
    PTIMERAPCROUTINE pfnCompletionRoutine, 
    LPVOID IpArgToCompletionRoutine, BOOL fResume); 


    304 ______________________________Windows   

         ,    
. ,  hTimer  ,    
.  2  (pDueTime  IPeriod)  : 
 ,       ,  , 
      .    
  ,       1  1999   
1:00 ,     6 : 
    
    //     
    HANDLE hTimer; 
    SYSTEMTIME st; 
    FILETIME ftLocal, ftUTC: 
    LARGE_INTEGER liUTC: 
    
    
    //  :     ,  
    //    ,      
    //  (. . "") 
    hTimer = CreateWaitableTimer(NULL, FALSE. NULL); 
    
    
    //       1  1999   1:00  
    //    
    st.wYear        = 1999: 
    
    
    st.wMonth       = 1;   //  
    st.wDayOfWeek   = 0;   //  
    st.wDay         = 1;   //    
    st.wHour        = 13; // 1  
    st.wMinute      =0;   //0  
    st.wSecond      =0;   //0  
    st.wMilliseconds= 0;   // 0  
    
    
    SystemTimeToFileTime(&st, SftLocal); 
    
    
    //     UTC- 
    LocalFileTimeToFileTime(&ftLocal, &ftUTC); 
    
    
    //  FILETIME  LARGE_INTEGER -     
    liUTC.LowPart = ftUTC.dwLowDateTime; 
    
    
    HUTC.HighPart = ftUTC.dwHighDateTime; 
    
    
    //   
    SetWaitabieTimer(hTimer, &liUTC, 6 * 60 * 60 * 1000, NULL, NULL, FALSE); 
    
    
          SYSTEMTIME,  
    (    ).  
    .     
LARGE_INTEGER *        
SYSTEMTIME.     FILETIME  LARGE_INTEGER 
:     32- .  ,   
  SYSTEMTIME  FILETIME.     
,   SetWaitableTimer   _  UTC 
(Coordinated Universal Time).     
 LocalFileTimeToFileTime.     FILETIME 
 LARGE_INTEGER ,        
SetWaitableTimer   FILETIME : 

    __________________________  10.   305 


    //   
    
    SetWaitableTimei-ChTimer, (PLARGE_INTEGER) &ftUTC, 
    6 * 60 * 60 * 1000. NULL, NULL, FALSE): 
    
     ,    ,    .    
!     FILETIME  LARGE_INTEGER , 
    -.    
FILETIME  ~ 32- ,    
 LARGE_INTEGER   64- .  SetWaitableTimer  
   FILETIME   ,     
     ,     FILETIME  
 64- .      ,   
LARGE_INTEGER      64- ,   
   FILETIME   LARGE_INTEGER,   
  SetWaitableTimer    LARGE_INTEGER. 

    /\ 

     86       - i 
.    SetWaitableTimer   FILETIME  
,        86.  
  (Alpha, MIPS  PowerPC)     
 EXCEPTION_DATATYPE_MISALIGNMENT,     
 . ,    ,    
      (   
 86)    .  ,   
    .       
      ! 

       ,      6  
(  1:00  1  1999 ),   IPeriod  
SetWaitableTimer.       
 ( ).   6 ,   , 
 21 600 000  (. . 6  * 60  * 60  * 1000 ). 
         SetWaitableTimer     
  ,        
.  ,      
   ,       ( 
);      .   
,        5  
  SetWaitableTimer. 
    
    //     
    HANDLE hTimer; 
    LARGE_INTEGER li; 
    //  ',     ,  
    //    ,      
    //  (, . "") 
    hTi^er"= CreaLeWaitableTimer(NULL, FALSE, NULL): 
    //     5    SetWaiLableTimer 
    const int nNanosecondsPerSecond = 1000000: 
    __int64 qwTlmeFroniNowInNanoseconds = 5 * nNanosecondsPerSecond; 
    
    
    . . . 

    306 _______________________________Windows   
    

    //    ,  SetWaitableTimer 
    // :   ,     
    qwTimeFromNowInNanoseconds = -qwTimeFromNowInNanoseconds; 
    
    
    //       (__lnt64) 
    
    
    //  LARGE_INTEGER 
    
    
    li.LowPart = (DWORD) (qwTimeFromNowInNanoseconds & OxFFFFFFFF); 
    
    
    li.HighPart = (LONG) (qwTimeFromNowInNanoseconds  32); 
    
    
    //        
    // ,      ,  
    //    
    SetWaitableTimer(hTimer, &li, 6 * 60 * 60 * 1000, NULL, NULL, FALSE): 
    
    
     ,     .    
 0   IPeriod.     (  
)          
  .      CloseHandle,  
 ,         
SetWaitableTimer   . 
    0', ,     ,    
   SetWaitableTimer. pfnCompletionRoutine  
IpArgToCompletionRoutine.     NULL       
   .         
   (asynchronous procedure call, APC)  , 
 SetWaitableTimer  ,   . ( 
        15.)   
   -      
SetWaitableTimer.      : 
    
    VOID APIENTRY TimerAPCRoutine(LPVOID IpArgToCompletionRoutine, 
    DWORD dwTimerLowValue, DWORD dwTimerHighValue) { 
    
    //   .   
    } 

        TimerAPCRoutine,       . 
      ,    
SetWaitableTimer    ,      
    (alertable) , . .    
   : SkepEx, WaitForSingleObjectEx, 
WaitForMultipkObjectsEx, MsgWaitForMultipleObjectsEx  SignalObjectAndWait. 
          ,   
   - ,       , 
  .     : 

    HANDLE hTimer = CreatewaitableTimer(NULL, FALSE, NULL); 
    SetWaitableTimer(hTimer. ..., TimerAPCRoutine, ...); 
    WaitForSingleObjectEx(hTimer. INFINITE, TRUE); 

        ,    WaitForSingleObjectEx  
   .      , 
 ,      ,   
-  . ,    , -   
   ,       
   ,    ,  .  
,  -    

    _________________________ 10.   307 

      ,   ,  ,    
- ,   . 
               
  ,      
 .       
IpArgToCompletionRoutine,    SetWaitable Timer.  
   TimerAPCRoutine -  (   
  ).   , dwTimerLowValue  
dwTimerHigh Value,    . ,  , 
,        : 
    
    VOID APIENTRY TimerAPCRoutine(LPVOID IpArgToCompletionRoutine, 
    D^RD dwTimerLowValue, DWORD dwTimerHighValue) { 
    
    FILETIME ftUTC, ftLocal; 
    SYSTEMTIME st; 
    TCHAR szBuf[256]: 
    
    //     FILETIME 
    ftUTC.dwLowDateTime = dwTimerLowValue; 
    
    ftUTC.dwHighDateTime = dwTimerHighValue; 
    
    //  UTC-   
    FileTimeToLocalFileTime(&ftUTC, &ftLocal); 
    
    //   FILETIME   SYSTEMTIME, 
    //     GetDateFormat  GetTimeFormat 
    FileTimeToSystemTime(&ftLocal, &st); 
    
    //      ,   
    //   
    GetDateFormat(LOGALE_USER_DEFAULT, DATE_LONGDATE, 
    &st, NULL, szBuf, sizeof(szBuf) / sizeof(TCHAR)); 
    _tcscat(szBuf. __TEXT(" ")); 
    GetTimeFormat(LOCALE_USER_DEFAULT, 0, 
    &st, NULL, _tcschr(szBuf, 0), 
    sizeof(szBuf) / sizeof(TCHAR) - _tcslen(szBuf)); 
    //    
    MessageBox(NULL, szBuf, "Timer went off at...", MB_OK); 
    } 

         SetWaitableTimer  fResume.    
    .     FALSE,   
       .   , ,  
,  Schedule-1-,      
   ,       
TRUE.   ,      (   
 ),   ,   .    
 - WAV-        . 
         ,    CancelWaitableTimer. 

    BOOL CancelWaitableTimer(HANDLE hTimer); 


    308 ._______________________________Windows   

             , 
      ,       
   SetWaitableTimer. ,    
 ,   CancelWaitableTimer   
  SetWaitableTimer  ;   SetWaitableTimer 
      . 
    , -  Windows-   
     User (   
SetTimer).  ,    ,      
,  ,   ,   User.  ,  
,      . 
     User   WM_TIMER,   , 
  SetTimer (     )   
  (   ).  ,   
 User    .      
  , ,      ,   
     . 
             - 
,    , , -,  
     User.    ,   
        ,   
 4. ,       
       , . .  
  .   WM_TIMER,     
11,      ,     
   . ,      
,      :   .  ,  
,  . 

       

        (    
)   WaitForSingleObject  WaitForMultipleObjects.  
   ,     . -   
 . 

     Sleep 

       : 

    VOID Sleep(DWORD cMilliseconds); 

           , 
    cMilliseconds. :    
      .  
 Sleep   cMilliseconds,  ,   
        .  
    ,   CritSecs. 
    4.      , ,   
MsgWaitForMultipleObjects      . 

    __________________________ 10.   309 


      / 

       /      
     . ,      
  ,        .   
    ,       
 ,      . . , 
          
 . 
     ,      ;  
 ,     WaitForSingleObject    
  .     
/,      .   
  ,     ,  
 ,       .   
   . 
      /     15. 

     WaitForInputIdle 

           WaitForInputIdle: 

    DWORD WaitForInputIdle(HANDLE hProcess, DWORD dwTimeout); 

      ,   ,   hProcess, 
  _^.,^    . 
WaitForInputIdle   , ,   , 
     -   .  
      CreateProcess,   
    ,    .   
   ,   .   
    ,   ,  
        
  ,      .   
 CreateProcess      WaitForInputIdle. 
               
 - . ,       : 
    
    WM_KEYDOWN            VK_MENU 
    WM_KEYDOWN            VK_F 
    WM_KEYUP               VK_F 
    WM_KEYUP               VK_MENU 
    WM_KEYDOWN            VK_0 
    WM_KEYUP               VK_0 
    
         ,     Alt+F, , 
        Open   
File.      ; ,    
  , Windows        
       ,     
  CreateWindow. ,    - .  
,     WM_KEY*,   
 WaitForInputIdle         ,  
Windows            
 .      

    310 ______________________________Windows   

            - ,  
       . 
      , ,      
16 Windows.        
,      ,         
,   .  WaitForInputIdle   . 

     MsgWaitForMultipleObjects 

            (  
) : 
    
    DWORD MsgWaitForMultipleOb]ects(DWORD dwCount, LPHANDLE IpHandles, 
    BOOL bWaitAll, DWORD dwMilliseconds, DWORD dwWakeMask); 
    
       WaitForMultipleObjects,    
  dwWakeMask.    ,  ,  
       . ,  
      ,       
     ,   : 

    MsgWaitForMultipleObjects(0, NULL. TRUE, INFINITE, QS_KEY | QS_MOUSE); 

              
,   dwCount  0,  IpHandles  NULL.   
     .       
,  bWaitAll      FALSE,     
   .  ,    ,    
        . 
         ,    
GetQueueStatus (      11). MsgWaitForMultipleObjects  
,       , 
  ,        .  
   -       
 ,  ,  MsgWaitForMultipleObjects  
.   ,      
WaitForMultipleObjects      ( 
WAIT_OBJECT_0  WAIT_OBJECT_0+divCon<-l).   dwWakeMask 
       .   
 MsgWaitForMultipleObjects   ,   
WAIT_OBJECT_0+ dwCount.      ,    
  FileChng   14. 

     WaitForDebugEvent 

        Win32    
 .  ,     
 ,    ,      
-  ,    .   
   : 

    BOOL WaitForDebugEvent(LPDEBUG_EVENT Ipde, DWORD dwTimeout); 

       WaitForDebugEvent,   . 
     ,   
WaitForDebugEvent  . ,     
Ipde,      .   
  ,     
 . 

    ___________________________ 10.   311 


     SignalObjectAndWait 

     Windows NT 4   ,     
        ,     
    : 
    
    BOOL SignalObJectAndWait(HANDLE hObJectToSignal, HANDLE hObjectToWaitOn 
    DWORD dwMilliseconds, BOOL bAlertable); 
    
     hObjectToSignal   ,   
;      SignalObjectAndWait  
WAIT_FAILED,   GetLastError  6 (ERROR_INVALID_HANDLE).  
SignalObjectAndWait      ,  
,   ReleaseMutex, ReleaseSemaphore ( ,  1)  ResetEvent. 

    VWINDOWS/  Windows 95  SignalObjectAndWait     
  .    ,   
,       Windows 95. 

     hObjectToWaitOn      : 
, , , , , ,    
 (.  14)   .  dwMilliseconds,  , 
,       ,   
bAlertable ,        
    - (   / 
   15). 
      ,       BOOL,  
       : WAIT_OBJECT_0, WAIT_TIMEOUT, 
WA"IT_FAILED, WAIT_ABANDONED  WAIT_IO_COMPLETION. 
     SignalObjectAndWait     Win32 API   
. -,         
 ,  ,       
   .   ,  
   ,     User,  ,   
 ,   600   (  86),  
  , ,  : 

    ReleaseMutex(hMutex); 
    WaitForSingleObject(hEvent, INFINITE); 

      1200  .   
  SignalObjectAndWait     . 
    -,   SignalObjectAndWait        
 ,     .  _.  
       PulseEvent.      
  , PulseEvent         
 .         ,   
   (pulse).   ,    
 : 

    //  -  
    SetEvent(hEventWorkerThreadDone); 
    WaitForSingleObJect(hEventMoreWorkToBeDone, INFINITE): 
    //   -  


    312 ______________________________Windows   

         ,   
- ,    SetEvent,   ( ) 
   .         : 

    Wait Fo rSing leOb ject(hEventWo r kei-Th read Done); 
    PulseEvent(hEventMoreWorkToBeDone); 

              
,     .   ,   , 
     SetEvent,      
 PulseEvent.    ,       
         SetEvent,      
WaitForSingleObject.         
 hEventMoreWorkToBeDone. 
          ,  SignalObjectAndWaih 

    II  -  

    SignalOb:]ectAndWait(hEventWorkerThreadDone, 
    hEventMoreWorkToBeDone, INFINITE, FALSE); 
    
    //   -  
    
        ,     
   .    ,  ,  
  ,      hEventMoreWorkToBeDone, 
 ,    ,   . 

     /nfer/oc/ced- 

     5 ,   : Interlockedlncrement, 
InterlockedDecrement, InterlockedExchange, InterlockedExchangeAdd  InterlockedCompareExchange. 

    LONG InterlockedIncrement(PLONG pIValue); 
    LONG InterlockedDecrement(PLONG pIValue); 
    LONG InterlockedExchange(PLONG pITarget, LONG IValue); 
    LONG InterlockedExchangeAdd(PLONG plAddend, LONG llncrement): 
    PVOID InterlockedCompareExchange(PVOID *Destination, PVOIO  PVuiLi 
Luinpci n-iu/. 

            
  LONG.  ,       
            
.       ,    
       . 
     ,   ,     
  ( LONG),        
           : 

    _________________________ 10.   313 
    

    //   LONG,    
    LONG IValue; 
    //       
    lValue++; 
    //   
    Interlockedlncrement(&lValue); 
    
        ,     
 (,   ).      LONG 
  ;,.Microsoft    Win32 API  
 . 
      Interlockedlncrement  InterlockedDecrement  
       LONG  1;   
   pIValue.      , 
       .     
   ,   .   
   0,      
 ,         
 .       MULTINST.C  MODUSE.C 
(.  12). 
     InterlockedExchange      
 LONG (     pITarget)  , 
   IValue.  -    
          . 
           .    
Interlocked,       
( LONG)   ,     . ?  
,   .     Interlockedlncrement   , 
      ,  ,  
 ,   .      
,   ,  Interlockedlncrement  . , 
,  ,     ,  ,   
      ,  - 
   . 
         Windows NT 4.    
,     Intel 486  . Microsoft 
  ^TirKEmT^Windows NT 4 ,     
  486 ; 386-   .    
 , ,   Windows 95. 
     InterlockedExchangeAdd  Interlockedlncrement  
InterlockedDecrement   ,      
   LONG  ,    1.   - 
,        : 

    LONG IVal = 5; 
    LONG lOngVal = InterlockedExchangeAdd(&lVal, -2); 
    //  lOngVal  5, a IVal - 3 

    314 ______________________________Windows   

     InterlockedCompareExchange     
   .       
LONG (    Destination)  ,   
 Comperand.   ,   Destination  
  Exchange, a  ,  Destination  . 
          Destination   5, 
,   ,       500: 

    LONG IVal = 5; 
    LONG lOrigVal = (LONG) InterlockedConipareExchange((PVOID) &lVal, 
    (PVOID) 500, (PVOID) 5); 
    //  lOrigVal  5, a IVal - 500 

       : 

    LONG IVal = 5; 
    LONG lOrigVal = (LONG) InterlockedCompareExchange((PVOID) &lVal, 
    (PVOID) 500, (PVOID) 10); 
    //   -igVal,  IVal   5 
    
          PVOID   
InterlockedCompareExchange. ,       
.     Microsoft ,    
InterlockedCompareExchange  ,    PVOID 
  PLONG.  ,     
  LONG. 
