Algebraic Topology and Distributed Computing

Download Report

Transcript Algebraic Topology and Distributed Computing

Multithread API’s
Adam Piotrowski
Grzegorz Jabłoński
Lecture IV
Synchronisation
• Mutexes
• Semaphores
• Condition Variables
2
Mutex
The mutual exclusion lock is the simplest and
most primitive synchronization variable. It
provides a single, absolute owner for the
section of code (thus a critical section) that it
brackets between the calls to
pthread_mutex_lock()
and pthread_mutex_unlock(). The first thread
that locks the mutex gets ownership, and any
subsequent attempts to lock it will fail, causing
the calling thread to go to sleep.
3
Mutex initialisation
NAME
pthread_mutex_init, pthread_mutex_destroy initializes mutex with attr or destroys the mutex,
making it unusable in any form
SYNOPSIS
#include <pthread.h>
int pthread_mutex_init(pthread_mutex_t *mutex,
const pthread_mutexattr_t *attr);
int pthread_mutex_destroy(pthread_mutex_t
*mutex);
4
Mutex unlock operation
NAME
pthread_mutex_unlock - unlocks mutex and wakes up the first
thread sleeping on it.
SYNOPSIS
#include <pthread.h>
int pthread_mutex_unlock(pthread_mutex_t *mutex);
5
Mutex example
thread 1
thread 2
add(request_t *request)
{
pthread_mutex_lock(&lock);
request->next = requests;
requests = request
pthread_mutex_unlock(&lock);
}
request_t *remove()
{ pthread_mutex_lock(&lock);
...sleeping...
request = requests;
requests = requests->next;
pthread_mutex_unlock(&lock)
return(request);
}
6
Mutex example
7
Semaphores
A counting semaphore6 is a variable that you can
increment arbitrarily high, but decrement only to
zero. A sem_post() operation increments the
semaphore, while a sem_wait() attempts to
decrement it. If the semaphore is greater than zero,
the operation succeeds; if not, then the calling
thread must go to sleep until a different thread
increments it.
8
Semaphores initialisation
NAME
sem_init, sem_destroy - initializes the semaphore to value. If
pshared is non-zero, then the semaphore will be sharable among
processes. This destroys the semaphore.
SYNOPSIS
#include <pthread.h>
int sem_init(sem_t *sem, int pshared, unsigned int value);
int sem_destroy(sem_t *sem);
9
Semaphores operations
NAME
sem_post, sem_wait, sem_trywait - function increments the value
of the semaphore or decrements the value of sem by one. If the
semaphore’s value is zero, sem_wait() blocks, waiting for the
semaphore to be incremented by another process or thread, while
sem_trywait() will return immediately.
SYNOPSIS
#include <pthread.h>
int sem_post(sem_t *sem);
int sem_trywait(sem_t *sem);
int sem_wait(sem_t *sem);
10
Semaphores operations
11
Semaphores operations
NAME
sem_open, sem_close - returns a pointer to the semaphore name.
All processes which call this on the same name will get the same
semaphore pointer or closes the named semaphore for this
process.
SYNOPSIS
#include <pthread.h>
sem_t *sem_open(char *name, int oflag,... );
int sem_close(sem_t *sem);
12
Semaphors example
13
Semaphors example
producer()
{ request_t *request;
while(1) {
request = get_request();
add(request);
sem_post(&requests_length);
}
}
request_t *get_request()
{ request_t *request;
request = (request_t *)
malloc(sizeof(request_t));
request->data = read_from_net();
return(request)
}
void process_request(request_t
*request)
{ process(request->data);
free(request);
}
consumer()
{ request_t *request;
while(1){
SEM_WAIT(&requests_length);
request = remove();
process_request(request);
}
}
14
Conditional Variables
15
Conditional Variable
initialisation
NAME
pthread_cond_init, pthread_cond_destroy - initializes
cond with att or destroys the condition variable,
making it unusable in any form.
SYNOPSIS
#include <pthread.h>
int pthread_cond_init(pthread_cond_t *cond, const
pthread_condattr_t *attr);
int pthread_cond_destroy(pthread_cond_t *cond);
16
Conditional Variable Wait
Operation
NAME
pthread_cond_wait, pthread_cond_timewait - atomically releases
mutex and causes the calling thread to block on cond. Upon
successful return, the mutex will be reacquired.
SYNOPSIS
#include <pthread.h>
int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t
*mutex);
int pthread_cond_timedwait(pthread_cond_t *cond,
pthread_mutex_t *mutex, const struct timespec *abstime);
17
Conditional Variable Signal
Operation
NAME
pthread_cond_signal, pthread_cond_broadcast - unblocks the
first thread (if any) blocked on a condition variable or unblocks all
threads blocked on a condition variable. You do not
know the order in which they awake.
SYNOPSIS
#include <pthread.h>
int pthread_cond_signal(pthread_cond_t *cond);
int pthread_cond_broadcast(pthread_cond_t *cond);
18
Conditional Variable Example
thread 1
thread 2
pthread_mutex_lock(&m);
while (!my_condition)
pthread_cond_wait(&c, &m);
... sleeping ...
pthread_mutex_lock(&m);
my_condition = TRUE;
pthread_mutex_unlock(&m);
pthread_cond_signal(&c);
do_thing()
pthread_mutex_unlock(&m);
19
Conditional Variable Example
20
Conditional Variable Example
void *producer(void *arg)
{ request_t *request;
while(1) {
request = get_request();
pthread_mutex_lock(&r_lock);
while (length >= 10)
pthread_cond_wait(&r_producer,
&r_lock);
add(request);
length++;
pthread_mutex_unlock(&r_lock);
pthread_cond_signal(&r_consumer);
}
}
void *consumer(void *arg)
{ request_t *request;
while(1)
{ pthread_mutex_lock(&r_lock);
while (length == 0)
pthread_cond_wait(&r_consumer,
&r_lock);
request = remove();
length--;
pthread_mutex_unlock(&r_lock);
pthread_cond_signal(&r_producer);
process_request(request);
}
}
21
Multithread API’s
Windows OS
22
Processes
NAME
CreateProcess - creates a new process and its primary thread.
SYNOPSIS
BOOL CreateProcess(LPCTSTR lpApplicationName,
LPTSTR lpCommandLine,
LPSECURITY_ATTRIBUTES lpProcessAttributes,
LPSECURITY_ATTRIBUTES lpThreadAttributes,
BOOL bInheritHandles,
DWORD dwCreationFlags,
LPVOID lpEnvironment,
LPCTSTR lpCurrentDirectory,
LPSTARTUPINFO lpStartupInfo,
LPPROCESS_INFORMATION lpProcessInformation );
23
Processes
NAME
CreateProcess - creates a new process and its primary thread.
SYNOPSIS
BOOL CreateProcess(
LPCTSTR lpApplicationName,
LPTSTR lpCommandLine,
LPSECURITY_ATTRIBUTES lpProcessAttributes,
LPSECURITY_ATTRIBUTES
lpThreadAttributes,
Pointer
to a null-terminated string
that specifies the module
BOOL bInheritHandles,
to execute.
DWORD dwCreationFlags,
LPVOID lpEnvironment,
LPCTSTR lpCurrentDirectory,
LPSTARTUPINFO lpStartupInfo,
LPPROCESS_INFORMATION lpProcessInformation ); 24
Processes
NAME
CreateProcess - creates a new process and its primary thread.
SYNOPSIS
BOOL CreateProcess(
LPCTSTR lpApplicationName,
LPTSTR lpCommandLine,
LPSECURITY_ATTRIBUTES lpProcessAttributes,
LPSECURITY_ATTRIBUTES lpThreadAttributes,
BOOLtobInheritHandles,
Pointer
a null-terminated string that specifies
DWORD
command
linedwCreationFlags,
to execute.
LPVOID lpEnvironment,
LPCTSTR lpCurrentDirectory,
LPSTARTUPINFO lpStartupInfo,
LPPROCESS_INFORMATION lpProcessInformation );
the
25
Processes
NAME
CreateProcess - creates a new process and its primary thread.
SYNOPSIS
BOOL CreateProcess(
LPCTSTR lpApplicationName,
LPTSTR lpCommandLine,
LPSECURITY_ATTRIBUTES lpProcessAttributes,
LPSECURITY_ATTRIBUTES lpThreadAttributes,
BOOL bInheritHandles,
DWORD dwCreationFlags,
LPVOID lpEnvironment,
A pointer
to a SECURITY_ATTRIBUTES structure that
LPCTSTRwhether
lpCurrentDirectory,
determines
the returned handle can be inherited by
lpStartupInfo,
childLPSTARTUPINFO
processes.
LPPROCESS_INFORMATION lpProcessInformation );
26
Processes
NAME
CreateProcess - creates a new process and its primary thread.
SYNOPSIS
BOOL CreateProcess(
LPCTSTR lpApplicationName,
LPTSTR lpCommandLine,
LPSECURITY_ATTRIBUTES lpProcessAttributes,
LPSECURITY_ATTRIBUTES lpThreadAttributes,
BOOL bInheritHandles,
DWORD dwCreationFlags,
LPVOID lpEnvironment,
If this parameter TRUE, each inheritable handle in the
LPCTSTR
calling
processlpCurrentDirectory,
is inherited by the new process.
LPSTARTUPINFO lpStartupInfo,
LPPROCESS_INFORMATION lpProcessInformation );
27
Processes
NAME
CreateProcess - creates a new process and its primary thread.
SYNOPSIS
BOOL CreateProcess(
LPCTSTR lpApplicationName,
LPTSTR lpCommandLine,
LPSECURITY_ATTRIBUTES lpProcessAttributes,
LPSECURITY_ATTRIBUTES lpThreadAttributes,
BOOL bInheritHandles,
DWORD dwCreationFlags,
LPVOID lpEnvironment,
LPCTSTR
lpCurrentDirectory,
Additional
creation
flags e.g. CREATE_NEW_CONSOLE,
LPSTARTUPINFO lpStartupInfo,
CREATE_SUSPENDED,
DETACHED_PROCESS
LPPROCESS_INFORMATION lpProcessInformation );
28
Processes
NAME
CreateProcess - creates a new process and its primary thread.
SYNOPSIS
BOOL CreateProcess(
LPCTSTR lpApplicationName,
LPTSTR lpCommandLine,
LPSECURITY_ATTRIBUTES lpProcessAttributes,
LPSECURITY_ATTRIBUTES lpThreadAttributes,
BOOL bInheritHandles,
DWORD dwCreationFlags,
LPVOID lpEnvironment,
LPCTSTR lpCurrentDirectory,
LPSTARTUPINFO lpStartupInfo,
A pointer
to the environment block
for the new process.
LPPROCESS_INFORMATION
lpProcessInformation
);
29
Processes
NAME
CreateProcess - creates a new process and its primary thread.
SYNOPSIS
BOOL CreateProcess(
LPCTSTR lpApplicationName,
LPTSTR lpCommandLine,
LPSECURITY_ATTRIBUTES lpProcessAttributes,
LPSECURITY_ATTRIBUTES lpThreadAttributes,
BOOL bInheritHandles,
DWORD dwCreationFlags,
LPVOID lpEnvironment,
LPCTSTR lpCurrentDirectory,
LPSTARTUPINFO lpStartupInfo,
LPPROCESS_INFORMATION lpProcessInformation );
The full path to the current directory for the process.
30
Processes
NAME
CreateProcess - creates a new process and its primary thread.
SYNOPSIS
BOOL CreateProcess(
LPCTSTR lpApplicationName,
LPTSTR lpCommandLine,
LPSECURITY_ATTRIBUTES lpProcessAttributes,
LPSECURITY_ATTRIBUTES lpThreadAttributes,
BOOL bInheritHandles,
DWORD dwCreationFlags,
A pointer to a STARTUPINFO
LPVOID lpEnvironment,
LPCTSTR lpCurrentDirectory,
LPSTARTUPINFO lpStartupInfo,
LPPROCESS_INFORMATION lpProcessInformation );
31
Processes
NAME
CreateProcess - creates a new process and its primary thread.
SYNOPSIS
BOOL CreateProcess(
LPCTSTR lpApplicationName,
LPTSTR lpCommandLine,
LPSECURITY_ATTRIBUTES lpProcessAttributes,
LPSECURITY_ATTRIBUTES lpThreadAttributes,
BOOL bInheritHandles,
DWORD dwCreationFlags,
A pointer to a PROCESS_INFORMATION structure that
LPVOID
lpEnvironment,
receives
identification
information about the new process.
LPCTSTR lpCurrentDirectory,
LPSTARTUPINFO lpStartupInfo,
LPPROCESS_INFORMATION lpProcessInformation );
32
Process example
void _tmain( int argc, TCHAR *argv[] ) {
STARTUPINFO si;
PROCESS_INFORMATION pi;
if( !CreateProcess(
NULL, // No module name (use command line)
argv[1], // Command line
NULL, // Process handle not inheritable
NULL, // Thread handle not inheritable
FALSE, // Set handle inheritance to FALSE
0, // No creation flags
NULL, // Use parent's environment block
NULL, // Use parent's starting directory
&si, // Pointer to STARTUPINFO structure
&pi ) // Pointer to PROCESS_INFORMATION structure )
{
printf( "CreateProcess failed (%d)\n", GetLastError() ); return; }
// Wait until child process exits.
WaitForSingleObject( pi.hProcess, INFINITE );
// Close process and thread handles.
CloseHandle( pi.hProcess );
33
CloseHandle( pi.hThread );
}
Threads
NAME
CreateThread- creates a thread to execute within the address
space of the calling process.
SYNOPSIS
HANDLE CreateThread(
LPSECURITY_ATTRIBUTES lpsa,
DWORD cbStack,
LPTHREAD_START_ROUTINE lpStartAddr,
LPVOID lpvThreadParam,
DWORD fdwCreate,
LPDWORD lpIDThread );
34
Threads
NAME
CreateThread- creates a thread to execute within the address
space of the calling process.
SYNOPSIS
HANDLE CreateThread(
LPSECURITY_ATTRIBUTES lpsa,
DWORD cbStack,
LPTHREAD_START_ROUTINE lpStartAddr,
LPVOID to
lpvThreadParam,
A pointer
a SECURITY_ATTRIBUTES structure that
DWORDwhether
fdwCreate,
determines
the returned handle can be inherited by
childLPDWORD
processes.lpIDThread );
35
Threads
NAME
CreateThread- creates a thread to execute within the address
space of the calling process.
SYNOPSIS
HANDLE CreateThread(
LPSECURITY_ATTRIBUTES lpsa,
DWORD cbStack,
LPTHREAD_START_ROUTINE lpStartAddr,
LPVOID lpvThreadParam,
fdwCreate,
The DWORD
initial size
of the stack, in bytes.
LPDWORD lpIDThread );
36
Threads
NAME
CreateThread- creates a thread to execute within the address
space of the calling process.
SYNOPSIS
HANDLE CreateThread(
LPSECURITY_ATTRIBUTES lpsa,
DWORD cbStack,
LPTHREAD_START_ROUTINE lpStartAddr,
LPVOID lpvThreadParam,
DWORD fdwCreate,
A pointer
to the
application-defined
function to be executed
LPDWORD
lpIDThread
);
by the thread and represents the starting address of the
thread.
DWORD ThreadProc(LPVOID lpParameter );
37
Threads
NAME
CreateThread- creates a thread to execute within the address
space of the calling process.
SYNOPSIS
HANDLE CreateThread(
LPSECURITY_ATTRIBUTES lpsa,
DWORD cbStack,
LPTHREAD_START_ROUTINE lpStartAddr,
LPVOID lpvThreadParam,
DWORD fdwCreate,
LPDWORD lpIDThread );
A pointer to a variable to be passed to the thread.
38
Threads
NAME
CreateThread- creates a thread to execute within the address
space of the calling process.
SYNOPSIS
HANDLE CreateThread(
LPSECURITY_ATTRIBUTES lpsa,
DWORD cbStack,
LPTHREAD_START_ROUTINE lpStartAddr,
LPVOID lpvThreadParam,
DWORD fdwCreate,
LPDWORD lpIDThread );
The flags that control the creation of the thread i.e.
CREATE_SUSPENDED.
39
Threads
NAME
CreateThread- creates a thread to execute within the address
space of the calling process.
SYNOPSIS
HANDLE CreateThread(
LPSECURITY_ATTRIBUTES lpsa,
DWORD cbStack,
LPTHREAD_START_ROUTINE lpStartAddr,
LPVOID lpvThreadParam,
DWORD fdwCreate,
LPDWORD lpIDThread );
A pointer to a variable that receives the thread identifier.
40
Threads - Example
int _tmain() {
PMYDATA pData[MAX_THREADS];
DWORD dwThreadId[MAX_THREADS];
HANDLE hThread[MAX_THREADS];
int i;
for( i=0; i<MAX_THREADS; i++ ) {
pData[i] = (PMYDATA) HeapAlloc(GetProcessHeap(),
HEAP_ZERO_MEMORY, sizeof(MYDATA));
pData->val1 = i; pData->val2 = i+100;
hThread[i] = CreateThread(
NULL, // default security attributes
0, // use default stack size
MyThread, // thread function
pData, // argument to thread function
0, // use default creation flags
&dwThreadId[i]); // returns the thread identifier
}}
WaitForMultipleObjects(MAX_THREADS, hThread, TRUE, INFINITE); // Close all
thread handles and free memory allocation.
for(i=0; i<MAX_THREADS; i++) { CloseHandle(hThread[i]); }
HeapFree(GetProcessHeap(), 0, pData[i]);
return 0;
}
41
What is wrong with
CreateThread function ?
A thread in an executable that calls the
C run-time library (CRT) should use
the _beginthreadex and
_endthreadex functions for thread
management rather than
CreateThread and ExitThread
42
_beginthreadex
NAME
_beginthreadex - creates a thread to execute within the address
space of the calling process.
SYNOPSIS
uintptr_t _beginthreadex(
void *security,
unsigned stack_size,
unsigned ( *start_address )( void * ),
void *arglist,
unsigned initflag,
unsigned *thrdaddr );
43
_beginthreadex
NAME
_beginthreadex - creates a thread to execute within the address
space of the calling process.
SYNOPSIS
uintptr_t _beginthreadex(
void *security,
unsigned stack_size,
unsigned
)( void * ),
Pointer
to ( a*start_address
SECURITY_ATTRIBUTES
structure that
void *arglist,
determines
whether the returned handle can be inherited by
childunsigned
processes.
initflag,
unsigned *thrdaddr );
44
_beginthreadex
NAME
_beginthreadex - creates a thread to execute within the address
space of the calling process.
SYNOPSIS
uintptr_t _beginthreadex(
void *security,
unsigned stack_size,
unsigned ( *start_address )( void * ),
void
*arglist,
Stack
size
for a new thread or 0.
unsigned initflag,
unsigned *thrdaddr );
45
_beginthreadex
NAME
_beginthreadex - creates a thread to execute within the address
space of the calling process.
SYNOPSIS
uintptr_t _beginthreadex(
void *security,
unsigned stack_size,
unsigned ( *start_address )( void * ),
void *arglist,
unsigned
initflag,
Start
address
of a routine that begins execution of a new
unsigned *thrdaddr );
thread.
46
_beginthreadex
NAME
_beginthreadex - creates a thread to execute within the address
space of the calling process.
SYNOPSIS
uintptr_t _beginthreadex(
void *security,
unsigned stack_size,
unsigned ( *start_address )( void * ),
void *arglist,
unsigned initflag,
unsigned
); to a new thread.
Argument
list*thrdaddr
to be passed
47
_beginthreadex
NAME
_beginthreadex - creates a thread to execute within the address
space of the calling process.
SYNOPSIS
uintptr_t _beginthreadex(
void *security,
unsigned stack_size,
unsigned ( *start_address )( void * ),
void *arglist,
unsigned initflag,
unsigned *thrdaddr );
Argument list to be passed to a new thread.
48
_beginthreadex
NAME
_beginthreadex - creates a thread to execute within the address
space of the calling process.
SYNOPSIS
uintptr_t _beginthreadex(
void *security,
unsigned stack_size,
unsigned ( *start_address )( void * ),
void *arglist,
unsigned initflag,
unsigned *thrdaddr );
Points to a 32-bit variable that receives the thread
identifierlist to be passed to a new thread.
49
_beginthreadex example
int main() {
HANDLE hThread;
unsigned threadID;
printf( "Creating second thread...\n" );
hThread = (HANDLE)_beginthreadex(
NULL,
0,
&SecondThreadFunc,
NULL,
0,
&threadID );
WaitForSingleObject( hThread, INFINITE );
CloseHandle( hThread );
}
50
ExitThread or return
• ExitThread is the preferred method
of exiting a thread in C code.
• Return is the preferred method of
exiting a thread in C++ code.
51
Synchronisation
• Synchronisation in user mode
– Atomic access
– Critical sections
• Synchronisation in kernel mode
– Wait functions
– Mutexes
– Semphores
52
SYNCHRONISATION IN
USER MODE
53
Interlock functions
•
•
•
•
•
•
•
•
•
•
•
•
InterlockedAdd
InterlockedAnd
InterlockedBitTestAndReset
InterlockedBitTestAndSet
InterlockedCompareExchangePointer
InterlockedDecrement
InterlockedExchange
InterlockedExchangeAdd
InterlockedExchangePointer
InterlockedIncrement
InterlockedOr
InterlockedXor
54
Interlock functions
• InterlockedAdd
• InterlockedAnd
• InterlockedBitTestAndReset
LONG
InterlockedAdd(LONG volatile* Addend, LONG Value );
• InterlockedBitTestAndSet
Performs
an atomic addition operation on the specified LONG
• InterlockedCompareExchangePointer
values.
• InterlockedDecrement
• InterlockedExchange
• InterlockedExchangeAdd
• InterlockedExchangePointer
• InterlockedIncrement
• InterlockedOr
• InterlockedXor
55
Interlock functions
• InterlockedAdd
• InterlockedAnd
• InterlockedBitTestAndReset
• InterlockedBitTestAndSet
• InterlockedCompareExchangePointer
• InterlockedDecrement
BOOLEAN
InterlockedBitTestAndSet(LONG volatile* Base,
• InterlockedExchange
LONG
Bit );
• InterlockedExchangeAdd
Tests
the specified bit of the specified LONG value and sets
it to 1. The operation is atomic.
• InterlockedExchangePointer
• InterlockedIncrement
• InterlockedOr
• InterlockedXor
56
Interlock functions
• InterlockedAdd
• InterlockedAnd
• InterlockedBitTestAndReset
• InterlockedBitTestAndSet
• InterlockedCompareExchangePointer
• InterlockedDecrement
• InterlockedExchange
PVOID
InterlockedCompareExchangePointer(PVOID volatile*
• InterlockedExchangeAdd
Destination,
PVOID Exchange, PVOID Comparand );
• InterlockedExchangePointer
The function compares the Destination value with the
• InterlockedIncrement
Comparand value. If the Destination value is equal to the
• InterlockedOr
Comparand value, the Exchange value is stored in the address
• InterlockedXor
specified
by Destination. Otherwise, no operation is
performed.
57
Interlock functions
• InterlockedAdd
• InterlockedAnd
• InterlockedBitTestAndReset
• InterlockedBitTestAndSet
• InterlockedCompareExchangePointer
• InterlockedDecrement
• InterlockedExchange
• InterlockedExchangeAdd
• InterlockedExchangePointer
• InterlockedIncrement
• InterlockedOr
• InterlockedXor
LONG InterlockedIncrement(PLONG Addend);
Increments a caller-supplied variable as an atomic operation.
58
Critical sections
void InitializeCriticalSection(
LPCRITICAL_SECTION lpCriticalSection );
Initializes a critical section object.
BOOL InitializeCriticalSectionAndSpinCount(
LPCRITICAL_SECTION lpCriticalSection,
DWORD dwSpinCount );
Initializes a critical section object and sets the spin
count for the critical section.
59
Critical sections
void EnterCriticalSection(
LPCRITICAL_SECTION pCriticalSection );
Waits for ownership of the specified critical section
object. The function returns when the calling thread
is granted ownership.
void LeaveCriticalSection( LPCRITICAL_SECTION
lpCriticalSection );
Releases ownership of the specified critical section
object.
60
Critical sections example
CRITICAL_SECTION CriticalSection;
int main()
{
if (!InitializeCriticalSectionAndSpinCount(&CriticalSection, 0x80000400) )
return 0; ...
}
// Release resources used by the critical section object.
DeleteCriticalSection(&CriticalSection)
DWORD ThreadProc( LPVOID lpParameter )
{
...
// Request ownership of the critical section.
EnterCriticalSection(&CriticalSection);
// Access the shared resource.
// Release ownership of the critical section.
LeaveCriticalSection(&CriticalSection);
...
}
61
SYNCHRONISATION IN
KERNEL MODE
62
Wait Functions
NAME
WaitForSingleObject - Waits until the
specified object is in the signaled state
or the time-out interval elapses.
SYNOPSIS
DWORD WaitForSingleObject(HANDLE
hHandle, DWORD dwMilliseconds );
63
Wait Functions
NAME
WaitForMultipleObjects - Waits until one or all
of the specified objects are in the signaled
state or the time-out interval elapses.
SYNOPSIS
DWORD WaitForMultipleObjects(DWORD
nCount, const HANDLE* lpHandles, BOOL
bWaitAll, DWORD dwMilliseconds );
64
CloseHandle
NAME
CloseHandle - Closes an open object
handle.
SYNOPSIS
BOOL CloseHandle(HANDLE hObject );
65
Events Objects
• The event object is useful in sending
a signal to a thread indicating that a
particular event has occurred.
66
Event Functions
•
•
•
•
CreateEvent
OpenEvent
SetEvent
ResetEvent
67
CreateEvent
NAME
CreateEvent- Creates or opens a named or unnamed event
object.
SYNOPSIS
HANDLE CreateEvent(
LPSECURITY_ATTRIBUTES lpEventAttributes,
BOOL bManualReset,
BOOL bInitialState,
LPCTSTR lpName );
68
ResetEvent
NAME
ResetEvent- Sets the specified event object to the
nonsignaled state.
SYNOPSIS
BOOL ResetEvent(HANDLE hEvent );
69
SetEvent
NAME
ResetEvent- Sets the specified event object to the signaled
state.
SYNOPSIS
BOOL SetEvent(HANDLE hEvent );
70
Event Example
HANDLE ghGlobalWriteEvent;
HANDLE ghReadEvents[THREADCOUNT];
void WriteToBuffer(VOID)
{
DWORD dwWaitResult, i;
ResetEvent(ghGlobalWriteEvent) )
dwWaitResult = WaitForMultipleObjects(
THREADCOUNT, // number of handles in array
ghReadEvents, // array of read-event handles
TRUE,
// wait until all are signaled
INFINITE); // indefinite wait
switch (dwWaitResult)
{
case WAIT_OBJECT_0:
printf("Main thread writing to the shared
buffer...\n");
break;
default:
printf("Wait error: %d\n", GetLastError());
ExitProcess(0);
}
SetEvent(ghGlobalWriteEvent);
for(i = 0; i < THREADCOUNT; i++)
SetEvent(ghReadEvents[i]));
}
DWORD ThreadProc(LPVOID lpParam)
{
DWORD dwWaitResult;
HANDLE hEvents[2];
hEvents[0] = *(HANDLE*)lpParam; // thread's read event
hEvents[1] = ghGlobalWriteEvent; // global write event
dwWaitResult = WaitForMultipleObjects(
2,
// number of handles in array
hEvents,
// array of event handles
TRUE,
// wait till all are signaled
INFINITE); // indefinite wait
}
switch (dwWaitResult)
{
case WAIT_OBJECT_0:
printf("Thread %d reading from buffer...\n",
GetCurrentThreadId());
break;
default:
printf("Wait error: %d\n", GetLastError());
ExitThread(0);
}
SetEvent(hEvents[0]);
return 1;
71
Semaphores
NAME
CreateSemaphore - Creates or opens a named or unnamed
semaphore object.
SYNOPSIS
HANDLE CreateSemaphore(
LPSECURITY_ATTRIBUTES lpSemaphoreAttributes,
LONG lInitialCount,
LONG lMaximumCount,
LPCTSTR lpName );
72
Semaphores
NAME
ReleaseSemaphore - Increases the count of the specified
semaphore object by a specified amount.
SYNOPSIS
BOOL ReleaseSemaphore(
HANDLE hSemaphore,
LONG lReleaseCount,
LPLONG lpPreviousCount );
73
Semaphore example
HANDLE ghSemaphore;
void main()
{
HANDLE aThread[THREADCOUNT];
DWORD ThreadID;
int i;
ghSemaphore = CreateSemaphore(
NULL,
// default security attributes
MAX_SEM_COUNT, // initial count
MAX_SEM_COUNT, // maximum count
NULL);
// unnamed semaphore
for( i=0; i < THREADCOUNT; i++ )
{
aThread[i] = CreateThread(
NULL,
// default security attributes
0,
// default stack size
(LPTHREAD_START_ROUTINE) ThreadProc,
NULL,
// no thread function arguments
0,
// default creation flags
&ThreadID); // receive thread identifier
}
WaitForMultipleObjects(THREADCOUNT, aThread, TRUE,
INFINITE);
for( i=0; i < THREADCOUNT; i++ )
CloseHandle(aThread[i]);
CloseHandle(ghSemaphore);
}
DWORD WINAPI ThreadProc( LPVOID lpParam )
{
DWORD dwWaitResult;
BOOL bContinue=TRUE;
while(bContinue)
{
dwWaitResult = WaitForSingleObject(
ghSemaphore, // handle to semaphore
0L);
// zero-second time-out interval
switch (dwWaitResult)
{
case WAIT_OBJECT_0:
bContinue=FALSE;
Sleep(5);
ReleaseSemaphore(
ghSemaphore, // handle to semaphore
1,
// increase count by one
NULL) );
// not interested in previous count
break;
case WAIT_TIMEOUT:
break;
}
}
return TRUE;
}
74
Mutex
NAME
CreateMutex- Creates or opens a named or unnamed mutex
object.
SYNOPSIS
HANDLE CreateMutex(
PSECURITY_ATTRIBUTES lpMutexAttributes,
BOOL bInitialOwner,
LPCTSTR lpName );
75
Mutex
NAME
ReleaseMutex - Releases ownership of the specified mutex
object.
SYNOPSIS
BOOL ReleaseMutex(HANDLE hMutex );
76
Mutex example
HANDLE ghMutex;
void main()
{
HANDLE aThread[THREADCOUNT];
DWORD ThreadID;
int i;
ghMutex = CreateMutex(
NULL,
// default security attributes
FALSE,
// initially not owned
NULL);
// unnamed mutex
for( i=0; i < THREADCOUNT; i++ )
{
aThread[i] = CreateThread(
NULL,
// default security attributes
0,
// default stack size
(LPTHREAD_START_ROUTINE)
WriteToDatabase,
NULL,
// no thread function arguments
0,
// default creation flags
&ThreadID); // receive thread identifier
}
WaitForMultipleObjects(THREADCOUNT, aThread, TRUE,
INFINITE);
for( i=0; i < THREADCOUNT; i++ )
CloseHandle(aThread[i]);
CloseHandle(ghMutex);
}
DWORD WINAPI WriteToDatabase( LPVOID lpParam )
{
DWORD dwCount=0, dwWaitResult;
while( dwCount < 20 )
{
dwWaitResult = WaitForSingleObject(
ghMutex, // handle to mutex
INFINITE); // no time-out interval
switch (dwWaitResult)
{
case WAIT_OBJECT_0:
__try {
printf("Thread %d writing to database...\n",
GetCurrentThreadId());
dwCount++;
}
__finally {
if (! ReleaseMutex(ghMutex))
{
// Deal with error.
}
}
break;
case WAIT_ABANDONED:
return FALSE;
}
}
return TRUE;
77
}
Advanced Thread Objects
• Thread pools
• Fibers
78
Thank You
79