Move the sources to trunk
[opencv] / apps / HMMDemo / multiprocdiv.h
1 #ifndef __MULTYPROCDIV_H__
2 #define __MULTYPROCDIV_H__
3
4 #include <winbase.h>
5 #include <crtdbg.h>
6
7 #ifdef _DEBUG
8     #define thrWriteToTrace0(mac_param0,mac_param1)                                               \
9             _RPT0(mac_param0,mac_param1)
10     #define thrWriteToTrace1(mac_param0,mac_param1,mac_param2)                                    \
11             _RPT1(mac_param0,mac_param1,mac_param2)
12     #define thrWriteToTrace2(mac_param0,mac_param1,mac_param2,mac_param3)                         \
13             _RPT2(mac_param0,mac_param1,mac_param2,mac_param3)
14     #define thrWriteToTrace3(mac_param0,mac_param1,mac_param2,mac_param3,mac_param4)              \
15             _RPT3(mac_param0,mac_param1,mac_param2,mac_param3,mac_param4)
16     #define thrWriteToTrace4(mac_param0,mac_param1,mac_param2,mac_param3,mac_param4,mac_param5)   \
17             _RPT4(mac_param0,mac_param1,mac_param2,mac_param3,mac_param4,mac_param5)
18 #else
19     #define thrWriteToTrace0(mac_param0,mac_param1)
20     #define thrWriteToTrace1(mac_param0,mac_param1,mac_param2)
21     #define thrWriteToTrace2(mac_param0,mac_param1,mac_param2,mac_param3)
22     #define thrWriteToTrace3(mac_param0,mac_param1,mac_param2,mac_param3,mac_param4)
23     #define thrWriteToTrace4(mac_param0,mac_param1,mac_param2,mac_param3,mac_param4,mac_param5)
24 #endif
25
26 #define NONE_FINISH_WORK -1
27 #define BRAKE_WORK -2
28
29 #define SET_CHILD_THREAD_PRIORITY(mac_handle)                                      \
30     SetThreadPriority( mac_handle, THREAD_PRIORITY_BELOW_NORMAL )
31
32 #if(_WIN32_WINNT >= 0x0400)
33     #define SET_CHILD_THREAD_AFFINITY_MASK(mac_handle,mac_mask)                    \
34         SetThreadAffinityMask( mac_handle, mac_mask )
35     #define SET_CHILD_THREAD_IDEAL_PROCESSOR(mac_handle,mac_number)                \
36         SetThreadIdealProcessor( mac_handle, (DWORD)mac_number )
37 #else
38     #define SET_CHILD_THREAD_AFFINITY_MASK(mac_handle,mac_mask)
39     #define SET_CHILD_THREAD_IDEAL_PROCESSOR(mac_handle,mac_number)
40 #endif
41
42 #define COMMON_GLOBAL_VARS(mac_functionName,mac_inputStructType)                   \
43 CRITICAL_SECTION mac_functionName##CritSect;                                       \
44 HANDLE mac_functionName##Event;                                                    \
45 volatile int mac_functionName##Message;                                            \
46 HANDLE mac_functionName##ThreadHandle;                                             \
47 mac_inputStructType mac_functionName##InputStruct
48
49
50 #define IS_THREAD_STILL_WORKING(mac_functionName)                                  \
51     ( mac_functionName##ThreadHandle ? true : false )
52
53 #define INPUT_STRUCT_COMMON_PARAMS()                                               \
54     int threadNum;                                                                 \
55     bool doNext;                                                                   \
56     HANDLE hThread;                                                                \
57     bool working
58
59 #define ENTER_THREAD_CRITICAL_SECTION()                                            \
60     EnterCriticalSection( criticalSection )
61
62 #define LEAVE_THREAD_CRITICAL_SECTION()                                            \
63     LeaveCriticalSection( criticalSection )
64
65 #define childParams (thrParams[thrTaskNum])
66
67 #define INIT_CHILD_THREAD_PARAMS(mac_inputStructType,mac_threadMessage)            \
68     mac_inputStructType* params = (mac_inputStructType*)param;                     \
69     int threadNum = params->threadNum;                                             \
70     CRITICAL_SECTION* criticalSect;                                                \
71     HANDLE event;                                                                  \
72     int* thrMessage = (int*)&mac_threadMessage;                                    \
73     bool anotherThreadBlocksVar
74
75 #define BEGIN_CHILD_THREAD_FUNCTION(mac_functionName,mac_inputStructTypeForChild)  \
76 DWORD mac_functionName##_child( LPVOID param )                                     \
77 {                                                                                  \
78     INIT_CHILD_THREAD_PARAMS( mac_inputStructTypeForChild,                         \
79         mac_functionName##Message );                                               \
80     criticalSect = &mac_functionName##CritSect;                                    \
81     event = mac_functionName##Event;                                               \
82     thrWriteToTrace1( _CRT_WARN, "Thread #%d begins\n", threadNum )
83
84 #define BEGIN_CHILD_THREAD_CORE()                                                  \
85     InterlockedExchange( (long*)&(params->working), (long)true );                  \
86     while( params->doNext )                                                        \
87     {                                                                              \
88         thrWriteToTrace1( _CRT_WARN, "Thread #%d core begins\n", threadNum )
89
90 #define END_CHILD_THREAD_CORE()                                                    \
91         if( !params->doNext ) {                                                    \
92             break;                                                                 \
93         }                                                                          \
94         thrWriteToTrace1( _CRT_WARN, "Thread #%d core ends\n", threadNum );        \
95         EnterCriticalSection( criticalSect );                                      \
96             params->doNext = false;                                                \
97             anotherThreadBlocksVar = true;                                         \
98             while( anotherThreadBlocksVar )                                        \
99             {                                                                      \
100                 if( *thrMessage == NONE_FINISH_WORK ) {                            \
101                     *thrMessage = threadNum;                                       \
102                     anotherThreadBlocksVar = false;                                \
103                 }                                                                  \
104                 else {                                                             \
105                     LeaveCriticalSection( criticalSect );                          \
106                         Sleep(0);                                                  \
107                     EnterCriticalSection( criticalSect );                          \
108                 }                                                                  \
109             }                                                                      \
110             thrWriteToTrace1( _CRT_WARN, "Thread #%d sends message\n", threadNum );\
111             SetEvent( event );                                                     \
112         LeaveCriticalSection( criticalSect );                                      \
113         thrWriteToTrace1( _CRT_WARN, "Thread #%d suspends\n", threadNum );         \
114         SuspendThread( params->hThread );                                          \
115         Sleep(0);                                                                  \
116         thrWriteToTrace1( _CRT_WARN, "Thread #%d resumes\n", threadNum );          \
117     }
118
119 #define END_CHILD_THREAD_FUNCTION()                                                \
120     thrWriteToTrace1( _CRT_WARN, "Thread #%d finishes\n", threadNum );             \
121     InterlockedExchange( (long*)&(params->working), (long)false );                 \
122     return 0;                                                                      \
123 }                                                                                  
124                                                                                    
125 #define EXIT_CTRL_THREAD(mac_threadHandle)                                         \
126     thrWriteToTrace0( _CRT_WARN, "Control thread exits\n" );                       \
127     if( eraseFunction ) {                                                          \
128         eraseFunction(params);                                                     \
129     }                                                                              \
130     CloseHandle( *event );                                                         \
131     DeleteCriticalSection( criticalSect );                                         \
132     mac_threadHandle = 0;                                                          \
133     return 0;                                                                      
134                                                                                    
135 #define WAIT_SINGLE_OBJECT_CTRL()                                                  \
136 WaitForSingleObject( *event, INFINITE );                                           \
137 if( *thrMessage == BRAKE_WORK ) {                                                  \
138     int j;                                                                         \
139     thrWriteToTrace0( _CRT_WARN, "Control thread got exit message" );              \
140     for( j = 0; j < numProc; j ++ )                                                \
141     {                                                                              \
142         if( thrParams[j].working == true ) {                                       \
143             thrParams[j].doNext = false;                                           \
144             ResumeThread( hThread[j] );                                            \
145         }                                                                          \
146     }                                                                              \
147     Sleep( 5000 );                                                                 \
148     for( j = 0; j < numProc; j ++ )                                                \
149     {                                                                              \
150         int termRes;                                                               \
151         if( thrParams[j].working == true )                                         \
152         {                                                                          \
153             char buf[256];                                                         \
154             if( termRes = TerminateThread( hThread[j], 1 ) )                       \
155             {                                                                      \
156                 FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM, 0, GetLastError(), 0,   \
157                     buf, 256, 0 );                                                 \
158                 thrWriteToTrace1( _CRT_WARN, "TerminateThread returned: %s\n",     \
159                     buf );                                                         \
160             }                                                                      \
161             else {                                                                 \
162                 FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM, 0, GetLastError(), 0,   \
163                     buf, 256, 0 );                                                 \
164                 thrWriteToTrace1( _CRT_WARN, "TerminateThread returned: %s\n",     \
165                     buf );                                                         \
166             }                                                                      \
167             WaitForSingleObject( hThread[j], 1000 );                               \
168         }                                                                          \
169     }                                                                              \
170     EXIT_CTRL_THREAD(*thisThreadHandle);                                           \
171 }                                                                                  
172
173 #define BEGIN_CTRL_THREAD_FUNCTION(mac_functionName,mac_inputStructType,mac_inputStructTypeForChild,\
174                 mac_eraseFunction,mac_beginFunction,mac_endFunction)                                \
175 DWORD mac_functionName##_ctrl( LPVOID param )                                                       \
176 {                                                                                                   \
177     mac_inputStructType* params = (mac_inputStructType*)param;                                      \
178     SYSTEM_INFO sysInfo;                                                                            \
179     int numProc;                                                                                    \
180     DWORD dwThread[32];                                                                             \
181     HANDLE hThread[32];                                                                             \
182     mac_inputStructTypeForChild thrParams[32];                                                      \
183     DWORD affMask = 0;                                                                              \
184     CRITICAL_SECTION* criticalSect = &mac_functionName##CritSect;                                   \
185     HANDLE* event = &mac_functionName##Event;                                                       \
186     HANDLE* thisThreadHandle = &mac_functionName##ThreadHandle;                                     \
187     int tasksNum;                                                                                   \
188     LPTHREAD_START_ROUTINE childFunction = (LPTHREAD_START_ROUTINE)mac_functionName##_child;        \
189     int thrTaskNum;                                                                                 \
190     int* thrMessage = (int*)&mac_functionName##Message;                                             \
191     bool (*eraseFunction)( void* ) = ( bool (*)( void* ) )mac_eraseFunction;                        \
192     bool (*beginFunction)( void* ) = ( bool (*)( void* ) )mac_beginFunction;                        \
193     bool (*endFunction)( void* ) = ( bool (*)( void* ) )mac_endFunction;                            \
194     int i;                                                                                          \
195     thrWriteToTrace0( _CRT_WARN, "Control thread begins\n" )
196
197 #define BEGIN_CTRL_THREAD_CORE(mac_tasksNum)                                       \
198     tasksNum = mac_tasksNum;                                                       \
199     InitializeCriticalSection( criticalSect );                                     \
200     *event = CreateEvent( 0, true, false, NULL );                                  \
201     GetSystemInfo( &sysInfo );                                                     \
202     numProc = sysInfo.dwNumberOfProcessors;                                        \
203     if( numProc > 32 ) {                                                           \
204         EXIT_CTRL_THREAD( *thisThreadHandle );                                     \
205     }                                                                              \
206     if( beginFunction ) {                                                          \
207         beginFunction( params );                                                   \
208     }                                                                              \
209     *thrMessage = NONE_FINISH_WORK;                                                \
210     for( i = 0; i <= tasksNum; i ++ )                                              \
211     {                                                                              \
212         if( i > 0 ) {                                                              \
213             i --;                                                                  \
214             thrWriteToTrace2( _CRT_WARN, "Control thread gives task #%d to"        \
215                 " thread #%d\n", i, thrTaskNum )
216
217 // givingTask
218
219 #define END_CTRL_THREAD_CORE()                                                     \
220             thrParams[thrTaskNum].doNext = true;                                   \
221             thrWriteToTrace1( _CRT_WARN, "Control thread resumes thread #%d\n",    \
222                 thrTaskNum );                                                      \
223             while( !ResumeThread( hThread[thrTaskNum] ) ) Sleep(0);                \
224             i ++;                                                                  \
225         }                                                                          \
226         if( i < tasksNum ) {                                                       \
227             if( i < numProc ) {                                                    \
228                 thrParams[i].threadNum = i;                                        \
229                 thrParams[i].working = true;                                       \
230                 thrWriteToTrace0( _CRT_WARN, "Control thread creates child"        \
231                     " thread\n" );                                                 \
232                 hThread[i] = CreateThread( NULL, 0, childFunction,                 \
233                     &(thrParams[i]), CREATE_SUSPENDED, &(dwThread[i]) );           \
234                 thrParams[i].hThread = hThread[i];                                 \
235                 thrParams[i].doNext = false;                                       \
236                 SET_CHILD_THREAD_PRIORITY( hThread[i] );                           \
237                 SET_CHILD_THREAD_AFFINITY_MASK( hThread[i], affMask );             \
238                 SET_CHILD_THREAD_IDEAL_PROCESSOR( hThread[i], (DWORD)i );          \
239                 thrTaskNum = i;                                                    \
240             }                                                                      \
241             else {                                                                 \
242             thrWriteToTrace0( _CRT_WARN, "Control thread waits for a message\n" ); \
243                 WAIT_SINGLE_OBJECT_CTRL();                                         \
244                 EnterCriticalSection( criticalSect );                              \
245                     ResetEvent( *event );                                          \
246                     thrTaskNum = *thrMessage;                                      \
247                     thrWriteToTrace1( _CRT_WARN, "Control thread got a message"    \
248                         " from thread #%d\n", thrTaskNum );                        \
249                     thrParams[thrTaskNum].doNext = true;                           \
250                     *thrMessage = NONE_FINISH_WORK;                                \
251                 LeaveCriticalSection( criticalSect );                              \
252             }                                                                      \
253         }                                                                          \
254     }                                                                              \
255     thrWriteToTrace0( _CRT_WARN, "Control thread waits for finishing all"          \
256         " threads\n" );                                                            \
257     for( i = tasksNum; i < numProc; i ++ ) {                                       \
258         thrParams[i].doNext = false;                                               \
259         ResumeThread( hThread[i] );                                                \
260         WaitForSingleObject( hThread[i], INFINITE );                               \
261     }                                                                              \
262     for( i = 0; i < numProc; i ++ )                                                \
263     {                                                                              \
264         thrWriteToTrace0( _CRT_WARN, "Control thread waits for message\n" );       \
265         WAIT_SINGLE_OBJECT_CTRL();                                                 \
266         EnterCriticalSection( criticalSect );                                      \
267             ResetEvent( *event );                                                  \
268             thrTaskNum = *thrMessage;                                              \
269             thrWriteToTrace1( _CRT_WARN, "Control thread got last message from"    \
270                 " thread #%d\n", thrTaskNum );                                     \
271             thrParams[thrTaskNum].doNext = false;                                  \
272             *thrMessage = NONE_FINISH_WORK;                                        \
273             while( !ResumeThread( hThread[thrTaskNum] ) ) Sleep(0);                \
274         LeaveCriticalSection( criticalSect );                                      \
275         WaitForSingleObject( hThread[thrTaskNum], INFINITE );                      \
276     }
277
278 #define END_CTRL_THREAD_FUNCTION()                                                 \
279     thrWriteToTrace0( _CRT_WARN, "Control thread is getting normal finishing\n" ); \
280     if( endFunction ) {                                                            \
281         endFunction( params );                                                     \
282     }                                                                              \
283     CloseHandle( *event );                                                         \
284     DeleteCriticalSection( criticalSect );                                         \
285     *thisThreadHandle = 0;                                                         \
286     return 0;                                                                      \
287 }
288
289 #define DEFINE_START_THREAD_FUNCTION(mac_functionName,mac_inputParams)             \
290 extern HANDLE mac_functionName##ThreadHandle;                                      \
291 bool mac_functionName##mac_inputParams
292
293 #define BEGIN_START_THREAD_FUNCTION(mac_functionName,mac_inputParams,              \
294         mac_inputStructType)                                                       \
295 bool mac_functionName##mac_inputParams                                             \
296 {                                                                                  \
297     static bool mac_functionName##StartsFirstTime = true;                          \
298     bool anotherThreadBlocksVar;                                                   \
299     mac_inputStructType* params = &mac_functionName##InputStruct;                  \
300     HANDLE* thrHandle = &mac_functionName##ThreadHandle;                           \
301     LPTHREAD_START_ROUTINE threadCtrlFunction =                                    \
302         (LPTHREAD_START_ROUTINE)mac_functionName##_ctrl;                           \
303     thrWriteToTrace0( _CRT_WARN, "Start function begins\n" );                      \
304     if( mac_functionName##StartsFirstTime ) {                                      \
305         mac_functionName##StartsFirstTime = false;                                 \
306         mac_functionName##ThreadHandle = 0;                                        \
307     }                                                                              \
308     if( mac_functionName##ThreadHandle ) {                                         \
309         EnterCriticalSection( &mac_functionName##CritSect );                       \
310             anotherThreadBlocksVar = true;                                         \
311             while( anotherThreadBlocksVar )                                        \
312             {                                                                      \
313                 if( mac_functionName##Message == NONE_FINISH_WORK ) {              \
314                     mac_functionName##Message = BRAKE_WORK;                        \
315                     anotherThreadBlocksVar = false;                                \
316                 }                                                                  \
317                 else {                                                             \
318                     LeaveCriticalSection( &mac_functionName##CritSect );           \
319                         Sleep(0);                                                  \
320                     EnterCriticalSection( &mac_functionName##CritSect );           \
321                 }                                                                  \
322             }                                                                      \
323             thrWriteToTrace0( _CRT_WARN, "Main thread sets break event\n" );       \
324             SetEvent( mac_functionName##Event );                                   \
325         LeaveCriticalSection( &mac_functionName##CritSect );                       \
326     }                                                                              \
327     else {
328         
329 #define END_START_THREAD_FUNCTION()                                                \
330         *thrHandle = CreateThread( NULL, 0,                                        \
331             (LPTHREAD_START_ROUTINE)threadCtrlFunction, params, 0, 0 );            \
332         SET_CHILD_THREAD_PRIORITY( *thrHandle );                                   \
333     }                                                                              \
334     thrWriteToTrace0( _CRT_WARN, "Start function ends\n" );                        \
335     return true;                                                                   \
336 }
337
338
339 #endif // if !defined __MULTYPROCDIV_H__