More on Windows thread and functions C program example
Compiler: Visual C++ Express Edition 2005
Compiled on Platform: Windows Xp Pro SP2
Target platform: none, just for learning and fun
Header file: Standard and Windows
Additional library: Windows Platform SDK
Additional project setting: Set project to be compiled as C
Project -> your_project_name Properties -> Configuration Properties -> C/C++ -> Advanced -> Compiled As: Compiled as C Code (/TC)
Other info: non-CLR or unmanaged.
To do: Demonstrate the Windows thread and Win32 C functions
To show: The various Windows threads and processes functions usage
// For WinXp as a target
#define _WIN32_WINNT 0x0501
#include <windows.h>
#include <stdio.h>
#define THREADCOUNT 5
DWORD dwTlsIndex;
// Function declarations and definitions...
VOID ErrorExit(LPTSTR lpszMessage)
{
fprintf(stderr, "%s\n", lpszMessage);
ExitProcess(0);
}
void MyCommonFunction(void)
{
LPVOID lpvData;
// Retrieve a data pointer for the current thread...
lpvData = TlsGetValue(dwTlsIndex);
if ((lpvData == 0) && (GetLastError() != 0))
ErrorExit(L"TlsGetValue() error!\n");
else
printf("TlsGetValue() is OK.\n");
// Use the data stored for the current thread...
printf("Common: thread %u: lpvData = %p\n\n", GetCurrentThreadId(), lpvData);
}
DWORD WINAPI MyThreadFunc(void)
{
LPVOID lpvData;
// Initialize the TLS index for this thread.
lpvData = (LPVOID) LocalAlloc(LPTR, 256);
if (!TlsSetValue(dwTlsIndex, lpvData))
ErrorExit(L"TlsSetValue() error!\n");
else
printf("TlsSetValue() is OK.\n");
printf("Thread %u: lpvData = %p\n", GetCurrentThreadId(), lpvData);
MyCommonFunction();
// Release the dynamic memory before the thread returns...
lpvData = TlsGetValue(dwTlsIndex);
if (lpvData != 0)
LocalFree((HLOCAL) lpvData);
return 0;
}
DWORD main(void)
{
DWORD IDThread;
HANDLE hThread[THREADCOUNT];
int i;
printf("Thread count is: %u\n", THREADCOUNT);
// Allocate a TLS index...
if ((dwTlsIndex = TlsAlloc()) == -1)
ErrorExit(L"TlsAlloc() failed");
else
printf("\nTlsAlloc() is OK.\n\n");
// Create multiple threads...
for (i = 0; i < THREADCOUNT; i++)
{
hThread[i] = CreateThread(NULL, // no security attributes
0, // use default stack size
(LPTHREAD_START_ROUTINE) MyThreadFunc, // thread function
NULL, // no thread function argument
0, // use default creation flags
&IDThread); // returns thread identifier
// Check the return value for success...
if (hThread[i] == NULL)
ErrorExit(L"CreateThread() error.\n");
else
printf("hThread[%u] is OK.\n", i);
}
for (i = 0; i < THREADCOUNT; i++)
WaitForSingleObject(hThread[i], INFINITE);
if (TlsFree(dwTlsIndex) == 0)
printf("TlsFree() failed!\n");
else
printf("TlsFree() is OK!\n");
return 0;
}
Output example:
Thread count is: 5
TlsAlloc() is OK.
hThread[0] is OK.
TlsSetValue() is OK.
Thread 3156: lpvData = 00153948
TlsGetValue() is OK.
Common: thread 3156: lpvData = 00153948
TlsSetValue() is OK.
hThread[1] is OK.
Thread 3160: lpvData = 00153948
TlsGetValue() is OK.
hThread[2] is OK.
Common: thread 3160: lpvData = 00153948
TlsSetValue() is OK.
hThread[3] is OK.
Thread 3164: lpvData = 00153A50
TlsGetValue() is OK.
hThread[4] is OK.
TlsSetValue() is OK.
Common: thread 3164: lpvData = 00153A50
TlsSetValue() is OK.
Thread 3168: lpvData = 00153948
Thread 3172: lpvData = 00153B58
TlsGetValue() is OK.
TlsGetValue() is OK.
Common: thread 3172: lpvData = 00153B58
Common: thread 3168: lpvData = 00153948
TlsFree() is OK!
Press any key to continue . . .