7-1

it2022-05-09  26

ReadWrit.h /*  * ReadWrit.h * * Sample code for Multithreading Applications in Win32 * This is from Chapter 7, Listing 7-1 * * Demonstrates an implementation of the * Readers/Writers algorithm. This version * gives preference to readers.  */ // / // //  Structure definition // typedef  struct  _RWLock{     //  Handle to a mutex that allows     //  a single reader at a time access     //  to the reader counter.     HANDLE    hMutex;     //  Handle to a semaphore that keeps     //  the data locked for either the     //  readers or the writers.     HANDLE    hDataLock;     //  The count of the number of readers.     //  Can legally be zero or one while     //  a writer has the data locked.      int         nReaderCount;} RWLock; // //  Reader/Writer prototypes // BOOL InitRWLock(RWLock  * pLock);BOOL DestroyRWLock(RWLock  * pLock);BOOL AcquireReadLock(RWLock  * pLock); int  ReleaseReadLock(RWLock  * pLock);BOOL AcquireWriteLock(RWLock  * pLock); int  ReleaseWriteLock(RWLock  * pLock);BOOL ReadOK(RWLock  * pLock);BOOL WriteOK(RWLock  * pLock);BOOL FatalError( char   * s);

 

代码 /*  * ReadWrit.c * * Sample code for "Multithreading Applications in Win32" * This is from Chapter 7, various listings. * * Demonstrates an implementation of the * Readers/Writers algorithm. This version * gives preference to readers.  */ #define  WIN32_LEAN_AND_MEAN #include  < stdio.h > #include  < stdlib.h > #include  < windows.h > #include  " ReadWrit.h " //  If we wait more than 2 seconds, then something is probably wrong! #define  MAXIMUM_TIMEOUT 2000 //  Here's the pseudocode for what is going on: // //  Lock for Reader: //   Lock the mutex //   Bump the count of readers //   If this is the first reader, lock the data //   Release the mutex // //  Unlock for Reader: //   Lock the mutex //   Decrement the count of readers //   If this is the last reader, unlock the data //   Release the mutex // //  Lock for Writer: //   Lock the data // //  Unlock for Reader: //   Unlock the data // / BOOL MyWaitForSingleObject(HANDLE hObject){    DWORD result;    result  =  WaitForSingleObject(hObject, MAXIMUM_TIMEOUT);     //  Comment this out if you want this to be non-fatal      if  (result  !=  WAIT_OBJECT_0)        FatalError( " MyWaitForSingleObject - Wait failed, you probably forgot to call release! " );     return  (result  ==  WAIT_OBJECT_0);}BOOL InitRWLock(RWLock  * pLock){    pLock -> nReaderCount  =   0 ;    pLock -> hDataLock  =  CreateSemaphore(NULL,  1 1 , NULL);     if  (pLock -> hDataLock  ==  NULL)         return  FALSE;    pLock -> hMutex  =  CreateMutex(NULL, FALSE, NULL);     if  (pLock -> hMutex  ==  NULL)    {        CloseHandle(pLock -> hDataLock);         return  FALSE;    }     return  TRUE;}BOOL DestroyRWLock(RWLock  * pLock){    DWORD result  =  WaitForSingleObject(pLock -> hDataLock,  0 );     if  (result  ==  WAIT_TIMEOUT)         return  FatalError( " DestroyRWLock - Can't destroy object, it's locked! " );    CloseHandle(pLock -> hMutex);    CloseHandle(pLock -> hDataLock);     return  TRUE;}BOOL AcquireReadLock(RWLock  * pLock){    BOOL result  =  TRUE;     if  ( ! MyWaitForSingleObject(pLock -> hMutex))         return  FALSE;      if ( ++ pLock -> nReaderCount  ==   1 )        result  =  MyWaitForSingleObject(pLock -> hDataLock);    ReleaseMutex(pLock -> hMutex);     return  result;}BOOL ReleaseReadLock(RWLock  * pLock){     int  result;    LONG lPrevCount;     if  ( ! MyWaitForSingleObject(pLock -> hMutex))         return  FALSE;     if  ( -- pLock -> nReaderCount  ==   0 )        result  =  ReleaseSemaphore(pLock -> hDataLock,  1 & lPrevCount);    ReleaseMutex(pLock -> hMutex);     return  result;}BOOL AcquireWriteLock(RWLock  * pLock){     return  MyWaitForSingleObject(pLock -> hDataLock);}BOOL ReleaseWriteLock(RWLock  * pLock){     int  result;    LONG lPrevCount;    result  =  ReleaseSemaphore(pLock -> hDataLock,  1 & lPrevCount);     if  (lPrevCount  !=   0 )        FatalError( " ReleaseWriteLock - Semaphore was not locked! " );     return  result;}BOOL ReadOK(RWLock  * pLock){     //  This check is not perfect, because we     //  do not know for sure if we are one of     //  the readers.      return  (pLock -> nReaderCount  >   0 );}BOOL WriteOK(RWLock  * pLock){    DWORD result;     //  The first reader may be waiting in the mutex,     //  but any more than that is an error.      if  (pLock -> nReaderCount  >   1 )         return  FALSE;     //  This check is not perfect, because we     //  do not know for sure if this thread was     //  the one that had the semaphore locked.     result  =  WaitForSingleObject(pLock -> hDataLock,  0 );     if  (result  ==  WAIT_TIMEOUT)         return  TRUE;     //  a count is kept, which was incremented in Wait.     result  =  ReleaseSemaphore(pLock -> hDataLock,  1 , NULL);     if  (result  ==  FALSE)        FatalError( " WriteOK - ReleaseSemaphore failed " );     return  FALSE;} // / /*  * Error handler  */ BOOL FatalError( char   * s){    fprintf(stdout,  " %s\n " , s);     //  Comment out exit() to prevent termination     exit(EXIT_FAILURE);     return  FALSE;}

 

代码 /*  * List.c * * Sample code for "Multithreading Applications in Win32" * This is from Chapter 7, Listing 7-1 * * Demonstrates an implementation of the * Readers/Writers algorithm. This version * gives preference to readers.  */ #define  WIN32_LEAN_AND_MEAN #include  < stdio.h > #include  < stdlib.h > #include  < windows.h > #include  " ReadWrit.h " // / // //  Structure definition // typedef  struct  _Node{     struct  _Node  * pNext;     char     szBuffer[ 80 ];} Node;typedef  struct  _List{    RWLock     lock ;    Node     * pHead;} List; // //  Linked list prototypes // BOOL InitRWLock(RWLock  * pLock);BOOL DeleteList(List  * pList);BOOL AddHead(List  * pList, Node  * node);BOOL DeleteHead(List  * pList);BOOL Insert(List  * pList, Node  * afterNode, Node  * newNode);Node  * Next(List  * pList, Node  * node); // //  Test functions prototypes // DWORD WINAPI LoadThreadFunc(LPVOID n);DWORD WINAPI SearchThreadFunc(LPVOID n);DWORD WINAPI DeleteThreadFunc(LPVOID n); // //  Global variables // //  This is the list we use for testing List  * gpList; // / List  * CreateList(){    List  * pList  =  GlobalAlloc(GPTR,  sizeof (List));     if  (InitRWLock( & pList -> lock ==  FALSE)    {        GlobalFree(pList);        pList  =  NULL;    }     return  pList;}BOOL DeleteList(List  * pList){    AcquireWriteLock( & pList -> lock );     while  (DeleteHead(pList))        ;    ReleaseWriteLock( & pList -> lock );    DestroyRWLock( & gpList -> lock );    GlobalFree(pList);     return  TRUE;}BOOL AddHead(List  * pList, Node  * pNode){     if  ( ! WriteOK( & pList -> lock ))         return  FatalError( " AddHead - not allowed to write! " );    pNode -> pNext  =  pList -> pHead;    pList -> pHead  =  pNode;}BOOL DeleteHead(List  * pList){    Node  * pNode;     if  ( ! WriteOK( & pList -> lock ))         return  FatalError( " AddHead - not allowed to write! " );     if  (pList -> pHead  ==  NULL)         return  FALSE;    pNode  =  pList -> pHead -> pNext;    GlobalFree(pList -> pHead);    pList -> pHead  =  pNode;     return  TRUE;}BOOL Insert(List  * pList, Node  * afterNode, Node  * newNode){     if  ( ! WriteOK( & pList -> lock ))         return  FatalError( " Insert - not allowed to write! " );     if  (afterNode  ==  NULL)    {        AddHead(pList, newNode);    }     else     {        newNode -> pNext  =  afterNode -> pNext;        afterNode -> pNext  =  newNode;    }}Node  * Next(List  * pList, Node  * pNode){     if  ( ! ReadOK( & pList -> lock ))    {        FatalError( " Next - Not allowed to read! " );         return  NULL;    }     if  (pNode  ==  NULL)         return  pList -> pHead;     else          return  pNode -> pNext;} // / DWORD WINAPI ThreadFunc(LPVOID); int  main(){    HANDLE  hThrds[ 4 ];     int      slot  =   0 ;     int         rc;     int         nThreadCount  =   0 ;    DWORD    dwThreadId;    gpList  =  CreateList();     if  ( ! gpList)        FatalError( " main - List creation failed! " );    hThrds[nThreadCount ++ =  CreateThread(NULL,         0 , LoadThreadFunc,  0 0 & dwThreadId );    hThrds[nThreadCount ++ =  CreateThread(NULL,         0 , SearchThreadFunc, (LPVOID) " pNode " 0 & dwThreadId );    hThrds[nThreadCount ++ =  CreateThread(NULL,         0 , SearchThreadFunc, (LPVOID) " pList " 0 & dwThreadId );    hThrds[nThreadCount ++ =  CreateThread(NULL,         0 , DeleteThreadFunc,  0 0 & dwThreadId );     /*  Now wait for all threads to terminate  */     rc  =  WaitForMultipleObjects(        nThreadCount,        hThrds,        TRUE,        INFINITE );     for  (slot = 0 ; slot < nThreadCount; slot ++ )        CloseHandle(hThrds[slot]);    printf( " \nProgram finished.\n " );    DeleteList(gpList);     return  EXIT_SUCCESS;} /*  * Slowly load the contents of "List.c" into the * linked list.  */ DWORD WINAPI LoadThreadFunc(LPVOID n){     int  nBatchCount;    Node  * pNode;    FILE *  fp  =  fopen( " List.c " " r " );     if  ( ! fp)    {        fprintf(stderr,  " ReadWrit.c not found\n " );        exit(EXIT_FAILURE);    }    pNode  =  GlobalAlloc(GPTR,  sizeof (Node));    nBatchCount  =  (rand()  %   10 +   2 ;    AcquireWriteLock( & gpList -> lock );     while  (fgets(pNode -> szBuffer,  sizeof (Node), fp))    {        AddHead(gpList, pNode);         //  Try not to hog the lock          if  ( -- nBatchCount  ==   0 )        {            ReleaseWriteLock( & gpList -> lock );            Sleep(rand()  %   5 );            nBatchCount  =  (rand()  %   10 +   2 ;            AcquireWriteLock( & gpList -> lock );        }        pNode  =  GlobalAlloc(GPTR,  sizeof (Node));    }    ReleaseWriteLock( & gpList -> lock );     return   0 ;} /*  * Every so often, walked the linked list * and figure out how many lines one string * appears (given as the startup param)  */ DWORD WINAPI SearchThreadFunc(LPVOID n){     int  i;     char   * szSearch  =  ( char   * )n;     for  (i = 0 ; i < 20 ; i ++ )    {         int         nFoundCount  =   0 ;        Node    * next  =  NULL;        AcquireReadLock( & gpList -> lock );        next  =  Next(gpList, next);         while  (next)        {             if  (strstr(next -> szBuffer, szSearch))                nFoundCount ++ ;            next  =  Next(gpList, next);        }        ReleaseReadLock( & gpList -> lock );        printf( " Found %d lines with '%s'\n " , nFoundCount, szSearch);        Sleep((rand()  %   30 ));    }     return   0 ;} /*  * Every so often, delete some entries in the list.  */ DWORD WINAPI DeleteThreadFunc(LPVOID n){     int  i;     for  (i = 0 ; i < 100 ; i ++ )    {        Sleep( 1 );        AcquireWriteLock( & gpList -> lock );        DeleteHead(gpList);        DeleteHead(gpList);        DeleteHead(gpList);        ReleaseWriteLock( & gpList -> lock );    }     return   0 ;}

od

 

转载于:https://www.cnblogs.com/nanshouyong326/archive/2010/07/12/1775807.html


最新回复(0)