public
Created

UserSyncCompare.cpp in 《Windows via C/C++》

  • Download Gist
UserSyncCompare.cpp
C++
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157
/******************************************************************************
Module: UserSyncCompare.cpp
Notices: 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 7
class 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 variable
SRWLOCK 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 section
InitializeCriticalSection(&g_cs);
MeasureConcurrentOperation(TEXT("Critical Section"), nThreads, CriticalSectionCallback);
// Don't forget to cleanup
DeleteCriticalSection(&g_cs);
 
// Prepare the mutex
g_hMutex = CreateMutex(NULL, false, NULL);
MeasureConcurrentOperation(TEXT("Mutex"), nThreads, MutexCallback);
CloseHandle(g_hMutex);
_tprintf(TEXT("\n"));
}
 
return(0);
}

Please sign in to comment on this gist.

Something went wrong with that request. Please try again.