source: trunk/testapp/threads/threads.c@ 21518

Last change on this file since 21518 was 21518, checked in by dmik, 15 years ago

Added the threads test app.

  • Property svn:eol-style set to native
File size: 5.1 KB
Line 
1/*
2 * Taken from here http://msdn.microsoft.com/en-us/library/ms682516%28v=VS.85%29.aspx
3 * and slightly modified to compile with Odin
4 */
5
6#include <windows.h>
7#include <tchar.h>
8
9#define MAX_THREADS 10
10#define BUF_SIZE 255
11
12#ifdef _MSC_VER
13#include <strsafe.h>
14#else
15#include <stdarg.h>
16void StringCchPrintf(LPTSTR pszDest, size_t cchDest,
17 LPCTSTR pszFormat, ...);
18void StringCchLength(LPCTSTR psz, size_t cchMax, size_t *pcch);
19#endif
20
21DWORD WINAPI MyThreadFunction( LPVOID lpParam );
22void ErrorHandler(LPTSTR lpszFunction);
23
24// Sample custom data structure for threads to use.
25// This is passed by void pointer so it can be any data type
26// that can be passed using a single void pointer (LPVOID).
27typedef struct MyData {
28 int val1;
29 int val2;
30} MYDATA, *PMYDATA;
31
32#ifndef _MSC_VER
33
34void StringCchPrintf(LPTSTR pszDest, size_t cchDest,
35 LPCTSTR pszFormat, ...)
36{
37 va_list ap;
38
39 va_start(ap, pszFormat);
40 vsnprintf(pszDest, cchDest, pszFormat, ap);
41 va_end(ap);
42}
43
44void StringCchLength(LPCTSTR psz, size_t cchMax, size_t *pcch)
45{
46 *pcch = strnlen(psz, cchMax);
47}
48
49#endif
50
51int _tmain()
52{
53 PMYDATA pDataArray[MAX_THREADS];
54 DWORD dwThreadIdArray[MAX_THREADS];
55 HANDLE hThreadArray[MAX_THREADS];
56
57 // Create MAX_THREADS worker threads.
58
59 int i;
60 for( i=0; i<MAX_THREADS; i++ )
61 {
62 // Allocate memory for thread data.
63
64 pDataArray[i] = (PMYDATA) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
65 sizeof(MYDATA));
66
67 if( pDataArray[i] == NULL )
68 {
69 // If the array allocation fails, the system is out of memory
70 // so there is no point in trying to print an error message.
71 // Just terminate execution.
72 ExitProcess(2);
73 }
74
75 // Generate unique data for each thread to work with.
76
77 pDataArray[i]->val1 = i;
78 pDataArray[i]->val2 = i+100;
79
80 // Create the thread to begin execution on its own.
81
82 hThreadArray[i] = CreateThread(
83 NULL, // default security attributes
84 0, // use default stack size
85 MyThreadFunction, // thread function name
86 pDataArray[i], // argument to thread function
87 0, // use default creation flags
88 &dwThreadIdArray[i]); // returns the thread identifier
89
90
91 // Check the return value for success.
92 // If CreateThread fails, terminate execution.
93 // This will automatically clean up threads and memory.
94
95 if (hThreadArray[i] == NULL)
96 {
97 ErrorHandler(TEXT("CreateThread"));
98 ExitProcess(3);
99 }
100 } // End of main thread creation loop.
101
102 // Wait until all threads have terminated.
103
104 WaitForMultipleObjects(MAX_THREADS, hThreadArray, TRUE, INFINITE);
105
106 // Close all thread handles and free memory allocations.
107
108 for(i=0; i<MAX_THREADS; i++)
109 {
110 CloseHandle(hThreadArray[i]);
111 if(pDataArray[i] != NULL)
112 {
113 HeapFree(GetProcessHeap(), 0, pDataArray[i]);
114 pDataArray[i] = NULL; // Ensure address is not reused.
115 }
116 }
117
118 return 0;
119}
120
121
122DWORD WINAPI MyThreadFunction( LPVOID lpParam )
123{
124 HANDLE hStdout;
125 PMYDATA pDataArray;
126
127 TCHAR msgBuf[BUF_SIZE];
128 size_t cchStringSize;
129 DWORD dwChars;
130
131 // Make sure there is a console to receive output results.
132
133 hStdout = GetStdHandle(STD_OUTPUT_HANDLE);
134 if( hStdout == INVALID_HANDLE_VALUE )
135 return 1;
136
137 // Cast the parameter to the correct data type.
138 // The pointer is known to be valid because
139 // it was checked for NULL before the thread was created.
140
141 pDataArray = (PMYDATA)lpParam;
142
143 // Print the parameter values using thread-safe functions.
144
145 StringCchPrintf(msgBuf, BUF_SIZE, TEXT("Parameters = %d, %d\n"),
146 pDataArray->val1, pDataArray->val2);
147 StringCchLength(msgBuf, BUF_SIZE, &cchStringSize);
148#ifdef _MSC_VER
149 WriteConsole(hStdout, msgBuf, (DWORD)cchStringSize, &dwChars, NULL);
150#else
151 // WriteConsole seems to be a stub in Odin yet
152 printf("%s", msgBuf);
153#endif
154
155 return 0;
156}
157
158
159
160void ErrorHandler(LPTSTR lpszFunction)
161{
162 // Retrieve the system error message for the last-error code.
163
164 LPVOID lpMsgBuf;
165 LPVOID lpDisplayBuf;
166 DWORD dw = GetLastError();
167
168 FormatMessage(
169 FORMAT_MESSAGE_ALLOCATE_BUFFER |
170 FORMAT_MESSAGE_FROM_SYSTEM |
171 FORMAT_MESSAGE_IGNORE_INSERTS,
172 NULL,
173 dw,
174 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
175 (LPTSTR) &lpMsgBuf,
176 0, NULL );
177
178 // Display the error message.
179
180 lpDisplayBuf = (LPVOID)LocalAlloc(LMEM_ZEROINIT,
181 (lstrlen((LPCTSTR) lpMsgBuf) + lstrlen((LPCTSTR) lpszFunction) + 40) * sizeof(TCHAR));
182 StringCchPrintf((LPTSTR)lpDisplayBuf,
183 LocalSize(lpDisplayBuf) / sizeof(TCHAR),
184 TEXT("%s failed with error %d: %s"),
185 lpszFunction, dw, lpMsgBuf);
186 MessageBox(NULL, (LPCTSTR) lpDisplayBuf, TEXT("Error"), MB_OK);
187
188 // Free error-handling buffer allocations.
189
190 LocalFree(lpMsgBuf);
191 LocalFree(lpDisplayBuf);
192}
193
Note: See TracBrowser for help on using the repository browser.