/******************************************************************************Module: UserSyncCompare.cppNotices: Copyright (c) 2008 Jeffrey Richter & Christophe Nasarre******************************************************************************/#include "..\CommonFiles\CmnHdr.h" /* See Appendix A. */#include <windows.h>#include <stdio.h>#include <tchar.h>// Stop watch class from Chapter 7class CStopwatch {public: CStopwatch() { QueryPerformanceFrequency(&m_liPerfFreq); Start(); } void Start() { QueryPerformanceCounter(&m_liPerfStart); } // Returns # of milliseconds since Start was called __int64 Now() const { LARGE_INTEGER liPerfNow; QueryPerformanceCounter(&liPerfNow); return(((liPerfNow.QuadPart - m_liPerfStart.QuadPart) * 1000) / m_liPerfFreq.QuadPart); }private: LARGE_INTEGER m_liPerfFreq; // Counts per second LARGE_INTEGER m_liPerfStart; // Starting count};DWORD g_nIterations = 1000000;typedef void (CALLBACK* OPERATIONFUNC)();DWORD WINAPI ThreadIterationFunction(PVOID operationFunc) {OPERATIONFUNC op = (OPERATIONFUNC) operationFunc; for (DWORD iteration = 0; iteration < g_nIterations; iteration++) { op(); } return 0;}void MeasureConcurrentOperation( TCHAR* operationName, DWORD nThreads, OPERATIONFUNC operationFunc) { HANDLE* phThreads = new HANDLE[nThreads]; SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_HIGHEST); for (DWORD currentThread = 0; currentThread < nThreads; currentThread++) { phThreads[currentThread] = CreateThread(NULL, 0, ThreadIterationFunction, operationFunc, 0, NULL); } SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_NORMAL); CStopwatch watch; WaitForMultipleObjects(nThreads, phThreads, TRUE, INFINITE); __int64 elapsedTime = watch.Now(); _tprintf( TEXT("Threads=%u, Milliseconds=%u, Test=%s\n"), nThreads, (DWORD)elapsedTime, operationName); // Don't forget to clean up the thread handles for (DWORD currentThread = 0; currentThread < nThreads; currentThread++) { CloseHandle(phThreads[currentThread]); } delete phThreads;}// -----------------------------------------------------------// List of tests to run:// -----------------------------------------------------------// Reading from a volatile int with NO synchronization at all// Writing to an int using InterlockedIncrement// Reading from a volatile int using critical sections// Read from a volatile int using SRWLock// Read from a volatile int using Mutex// -----------------------------------------------------------volatile LONG gv_value = 0;// 'lValue': local variable is initialized but not referenced#pragma warning(disable:4189)void WINAPI VolatileReadCallback(){ LONG lValue = gv_value; }#pragma warning(default:4189)void WINAPI VolatileWriteCallback(){ gv_value = 0; }void WINAPI InterlockedIncrementCallback(){InterlockedIncrement(&gv_value);}CRITICAL_SECTION g_cs;void WINAPI CriticalSectionCallback(){EnterCriticalSection(&g_cs);gv_value = 0;LeaveCriticalSection(&g_cs);}HANDLE g_hMutex;void WINAPI MutexCallback(){WaitForSingleObject(g_hMutex, INFINITE);gv_value = 0;ReleaseMutex(g_hMutex);}// Slim Reader/Writer Lock global variableSRWLOCK g_srwLock;void WINAPI SRWLockReadCallback() {AcquireSRWLockShared(&g_srwLock);gv_value = 0;ReleaseSRWLockShared(&g_srwLock);}void WINAPI SRWLockWriteCallback() {AcquireSRWLockExclusive(&g_srwLock);gv_value = 0;ReleaseSRWLockExclusive(&g_srwLock);}int _tmain(int argc, _TCHAR* argv[]) { for (int nThreads = 1; nThreads <= 4; nThreads *= 2) { MeasureConcurrentOperation(TEXT("Volatile Read"), nThreads, VolatileReadCallback);MeasureConcurrentOperation(TEXT("Volatile Write"), nThreads, VolatileWriteCallback);MeasureConcurrentOperation(TEXT("Interlocked Increment"), nThreads, InterlockedIncrementCallback);// Prepare the critical sectionInitializeCriticalSection(&g_cs);MeasureConcurrentOperation(TEXT("Critical Section"), nThreads, CriticalSectionCallback);// Don't forget to cleanupDeleteCriticalSection(&g_cs); // Prepare the Slim Reader/Writer lockInitializeSRWLock(&g_srwLock);MeasureConcurrentOperation(TEXT("SRWLock Read"), nThreads, SRWLockReadCallback);MeasureConcurrentOperation(TEXT("SRWLock Write"), nThreads, SRWLockWriteCallback);// NOTE: You can't cleanup a Slim Reader/Writer lock// Prepare the mutexg_hMutex = CreateMutex(NULL, false, NULL);MeasureConcurrentOperation(TEXT("Mutex"), nThreads, MutexCallback);CloseHandle(g_hMutex);_tprintf(TEXT("\n"));} system("pause");return(0);}
Threads=1, Milliseconds=33, Test=Volatile Read
Threads=1, Milliseconds=30, Test=Volatile Write
Threads=1, Milliseconds=47, Test=Interlocked Increment
Threads=1, Milliseconds=71, Test=Critical Section
Threads=1, Milliseconds=80, Test=SRWLock Read
Threads=1, Milliseconds=63, Test=SRWLock Write
Threads=1, Milliseconds=953, Test=Mutex
Threads=2, Milliseconds=34, Test=Volatile Read
Threads=2, Milliseconds=42, Test=Volatile Write
Threads=2, Milliseconds=67, Test=Interlocked Increment
Threads=2, Milliseconds=211, Test=Critical Section
Threads=2, Milliseconds=0, Test=SRWLock Read
Threads=2, Milliseconds=88, Test=SRWLock Write
Threads=2, Milliseconds=3668, Test=Mutex
Threads=4, Milliseconds=36, Test=Volatile Read
Threads=4, Milliseconds=83, Test=Volatile Write
Threads=4, Milliseconds=70, Test=Interlocked Increment
Threads=4, Milliseconds=374, Test=Critical Section
Threads=4, Milliseconds=184, Test=SRWLock Read
Threads=4, Milliseconds=198, Test=SRWLock Write
Threads=4, Milliseconds=8474, Test=Mutex
請按任意鍵繼續. . .