代码 /* * 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
