Game Development Reference
In-Depth Information
InitializeCriticalSection(&g_criticalSection);
for (int i=0; i<20; i++)
{
HANDLE m_hThread = CreateThread(
NULL, // default security attributes
0, // default stack size
(LPTHREAD_START_ROUTINE) ThreadProc,
&g_maxLoops, // thread parameter is how many loops
0,
// default creation flags
NULL);
// receive thread identifier
}
}
The call to
InitializeCriticalSection()
does exactly what it advertises
it
initializes the critical section object, declared globally as
CRITICAL_SECTION
g_criticalSection
. You should treat the critical section object as opaque and
not copy it or attempt to modify it. The thread procedure makes calls to
Enter-
CriticalSection()
and
LeaveCriticalSection()
around the access to the
shared global variable,
g_ProtectedTotal
.
If another thread is already in the critical section, the call to
EnterCritical-
Section()
will block and wait until the other thread leaves the critical section. Win-
dows does not guarantee any order in which the threads will get access, but it will be
fair to all threads. Notice that the critical section is made as small as possible
—
not
even the increment to the
dwCount
member variable is inside. This is to illustrate an
important point about critical sections: In order to achieve the maximum throughput,
you should minimize the time spent in critical sections as much as possible.
If you want to check the critical section and only enter it if it is not locked, you can
call
TryEnterCriticalSection()
. This function will return
true
only if the crit-
ical section is validly entered by the calling thread.
There are two useful C++ classes that help manage the creation and use of critical
sections,
CriticalSection
and
ScopedCriticalSection.
—
class CriticalSection : public GCC_noncopyable
{
public:
CriticalSection() { InitializeCriticalSection( &m_cs ); }
˜
CriticalSection(){ DeleteCriticalSection( &m_cs ); }
void Lock()
{ EnterCriticalSection( &m_cs ); }
void Unlock()
{ LeaveCriticalSection( &m_cs ); }
protected: