www.pudn.com > claar.zip > RWTEST.CPP


// Multiple-reader/Single-writer Lock in Windows NT 
// Demonstration Application 
// Author: Jeff Claar 
 
#define STRICT 
#define WIN32_LEAN_AND_MEAN 
#include  
#include  
#include  
#include  
#include "rwlock.hpp" 
 
// Event used to inform threads to terminate. 
HANDLE gTerminateEvent; 
 
// The read thread.  This thread simulates a reader that 
// obtains a shared lock.  It holds the lock for a few 
// seconds, then releases it. 
DWORD CALLBACK sReadThread(LPVOID rwLock) 
{ 
    SyRWLock* pLock = (SyRWLock *) rwLock; 
    DWORD dwId = GetCurrentThreadId(); 
 
    // Loop until the user presses ENTER. 
    while (WaitForSingleObject(gTerminateEvent, 0) == 
        WAIT_TIMEOUT) 
    { 
        printf("Read thread %d trying to get shared\n", dwId); 
 
        pLock->GetShared(TRUE); 
 
        printf("Read thread %d got shared\n", dwId); 
 
        // Got the shared lock.  Sleep for a few seconds. 
        // Other read threads can acquire a shared lock 
        // at this point, but no write threads can 
        // acquire an exclusive lock. 
        Sleep((3000 * rand()) / RAND_MAX); 
 
        printf("Read thread %d releasing shared\n", dwId); 
 
        pLock->Release(); 
 
        // Not holding any lock.  Sleep again. 
        Sleep((1000 * rand()) / RAND_MAX); 
    } 
    return 0; 
} 
 
// The write thread.  This thread simulates a writer that 
// obtains an exclusive lock.  It holds the lock for 
// a few seconds, then releases it. 
DWORD CALLBACK sWriteThread(LPVOID rwLock) 
{ 
    SyRWLock* pLock = (SyRWLock *) rwLock; 
    DWORD dwId = GetCurrentThreadId(); 
 
    while (WaitForSingleObject(gTerminateEvent, 0) == 
        WAIT_TIMEOUT) 
    { 
        printf("Write thread %d trying to get exclusive\n", dwId); 
        pLock->GetExclusive(TRUE); 
 
        // Now have the exclusive lock.  Get a shared lock too 
        // just to show it can be done. 
        pLock->GetShared(TRUE); 
 
        printf("Write thread %d got exclusive\n", dwId); 
 
        // Sleep for a moment.  No read threads 
        // can obtain the lock at this point. 
        Sleep((4000 * rand()) / RAND_MAX); 
 
        printf("Write thread %d releasing exclusive\n", dwId); 
 
        // Release the lock.  We must release the lock twice 
        // because it was acquired twice. 
        pLock->Release(); 
        pLock->Release(); 
 
        // Sleep for a moment again while not holding 
        // any lock. 
        Sleep((3000 * rand()) / RAND_MAX); 
    } 
    return 0; 
} 
 
extern "C" 
int main(int argc, char* argv[]) 
{ 
    srand(time(NULL)); 
 
    if (argc != 3) 
    { 
       printf("Usage: rwtest  \n"); 
       return -1; 
    } 
    int numReaders = atoi(argv[1]); 
    int numWriters = atoi(argv[2]); 
 
    printf("Press  to quit.\n"); 
 
    // Create the MRSW resource that will be used be this 
    // application. 
    SyRWLock rwl; 
 
    // Create an event to inform threads to terminate. 
    gTerminateEvent = CreateEvent(NULL, TRUE, FALSE, NULL); 
 
    // Create the read and write threads.  The 
    // MRSW lock is passed as an argument to the thread. 
    HANDLE* hThreads = new HANDLE[numReaders + numWriters]; 
    DWORD   id; 
    int     i; 
    for (i = 0; i < numReaders; i++) 
    { 
        hThreads[i] = CreateThread(NULL, 0, 
            sReadThread, &rwl, 0, &id); 
    } 
 
    for (i = 0; i < numWriters; i++) 
    { 
        hThreads[i + numReaders] = CreateThread(NULL, 0, 
            sWriteThread, &rwl, 0, &id); 
    } 
 
    // Wait for the user to press ENTER. 
    getchar(); 
 
    // Inform the threads that they should terminate. 
    SetEvent(gTerminateEvent); 
 
    printf("Waiting for threads to terminate...\n"); 
    WaitForMultipleObjects(numReaders + numWriters, 
        hThreads, TRUE, INFINITE); 
 
    // Close handles and exit. 
    for (i = 0; i < numReaders + numWriters; i++) 
    { 
        CloseHandle(hThreads[i]); 
    } 
 
    delete [] hThreads; 
 
    CloseHandle(gTerminateEvent); 
 
    return 0; 
}