KWStyle - itkMultiThreader.cxx
 
Matrix View
Description

1 /*=========================================================================
2
3   Program:   Insight Segmentation & Registration Toolkit
4   Module:    $RCSfile: itkMultiThreader.cxx.html,v $
5   Language:  C++
6   Date:      $Date: 2006/01/17 19:15:42 $
7   Version:   $Revision: 1.4 $
8
9   Copyright (c) Insight Software Consortium. All rights reserved.
10   See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details.
11
12   Portions of this code are covered under the VTK copyright.
13   See VTKCopyright.txt or http://www.kitware.com/VTKCopyright.htm for details.
14
15      This software is distributed WITHOUT ANY WARRANTY; without even 
16      the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
17 IND *****PURPOSE.  See the above copyright notices for more information.
18
19 DEF =========================================================================*/
20
21 #include "itkMultiThreader.h"
22 #include "itkObjectFactory.h"
23 #ifndef _WIN32
24 #include <unistd.h>
25 #endif
26 #ifdef _WIN32
27 #pragma warning ( disable : 4786 )
28 #include "itkWindows.h"
29 #include <process.h>
30 #endif
31
32 #ifdef ITK_USE_SPROC
33 #include <sys/prctl.h>
34 #include <wait.h>
35 #include <errno.h>
36 #include <sys/types.h>
37 #include <sys/mman.h>
38 #include <sys/resource.h>
39 #endif
40
41 namespace itk {
42 extern "C"
43 {
44 TDR   typedef void*(*c_void_cast)(void*);
45 }
46   
47 LEN // Initialize static member that controls global maximum number of threads : 0 => Not initialized.
48 int MultiThreader::m_GlobalMaximumNumberOfThreads = 0;
49 int MultiThreader::m_GlobalDefaultNumberOfThreads = 0;
50
51 void MultiThreader::SetGlobalMaximumNumberOfThreads(int val)
52 {
53   if (val == m_GlobalMaximumNumberOfThreads)
54     {
55     return;
56     }
57   m_GlobalMaximumNumberOfThreads = val;
58 }
59   
60 int MultiThreader::GetGlobalMaximumNumberOfThreads()
61 {
62   return m_GlobalMaximumNumberOfThreads;
63 }
64
65 void MultiThreader::SetGlobalDefaultNumberOfThreads(int val)
66 {
67   if (val == m_GlobalDefaultNumberOfThreads)
68     {
69     return;
70     }
71   m_GlobalDefaultNumberOfThreads = val;
72 }
73
74 int MultiThreader::GetGlobalDefaultNumberOfThreads()
75 {
76   if (m_GlobalDefaultNumberOfThreads == 0)
77     {
78     int num;
79 #ifdef ITK_USE_SPROC
80     // Default the number of threads to be the number of available
81     // processors if we are using sproc()
82     num = prctl( PR_MAXPPROCS );
83 #endif
84     
85 #ifdef ITK_USE_PTHREADS
86     // Default the number of threads to be the number of available
87     // processors if we are using pthreads()
88 #ifdef _SC_NPROCESSORS_ONLN
89     num = sysconf( _SC_NPROCESSORS_ONLN );
90 #elif defined(_SC_NPROC_ONLN)
91     num = sysconf( _SC_NPROC_ONLN );
92 IND #else
93     num = 1;
94 #endif
95 #if defined(__SVR4) && defined(sun) && defined(PTHREAD_MUTEX_NORMAL)
96     pthread_setconcurrency(num);
97 #endif
98 #endif
99     
100 #if defined(_WIN32)
101 IND ****{
102 IND **SYSTEM_INFO sysInfo;
103 IND **GetSystemInfo(&sysInfo);
104 IND **num = sysInfo.dwNumberOfProcessors;
105 IND ****}
106 #endif
107     
108 #ifndef ITK_USE_WIN32_THREADS
109 #ifndef ITK_USE_SPROC
110 #ifndef ITK_USE_PTHREADS
111     // If we are not multithreading, the number of threads should
112     // always be 1
113     num = 1;
114 #endif  
115 #endif  
116 #endif
117     
118     // Limit the number of threads
119     if (num > ITK_MAX_THREADS)
120       {
121       num = ITK_MAX_THREADS;
122       }
123     m_GlobalDefaultNumberOfThreads = num;
124     }
125   
126   return m_GlobalDefaultNumberOfThreads;
127 }
128
129 // Constructor. Default all the methods to NULL. Since the
130 // ThreadInfoArray is static, the ThreadIDs can be initialized here
131 // and will not change.
132 #ifdef ITK_USE_SPROC
133 bool      MultiThreader::m_Initialized = false;
134 usptr_t * MultiThreader::m_ThreadArena= 0;
135 int       MultiThreader::m_DevzeroFd  = -1;
136
137 void MultiThreader::Initialize()
138 {
139   usconfig(CONF_ARENATYPE, US_SHAREDONLY);
140 LEN   //  usconfig(CONF_INITSIZE, 256*1024*1024); // not to be used if we are auto growing the arena
141   usconfig(CONF_INITUSERS, (unsigned int) ITK_MAX_THREADS);
142   
143   usconfig(CONF_AUTOGROW, 1);
144   usconfig(CONF_AUTORESV, 1);
145   
146   MultiThreader::m_ThreadArena = usinit("/dev/zero");
147   
148   int code= usadd (MultiThreader::m_ThreadArena);
149   
150   MultiThreader::m_Initialized = true;
151   
152   MultiThreader::m_DevzeroFd= open("/dev/zero", O_RDWR);
153 }
154 #endif
155
156 MultiThreader::MultiThreader()
157 {
158   for (int i = 0; i < ITK_MAX_THREADS; i++)
159     {
160     m_ThreadInfoArray[i].ThreadID           = i;
161     m_ThreadInfoArray[i].ActiveFlag         = 0;
162     m_ThreadInfoArray[i].ActiveFlagLock     = 0;
163     
164     m_MultipleMethod[i]                     = 0;
165     m_MultipleData[i]                       = 0;
166     
167     m_SpawnedThreadActiveFlag[i]            = 0;
168     m_SpawnedThreadActiveFlagLock[i]        = 0;
169     m_SpawnedThreadInfoArray[i].ThreadID    = i;
170     }
171   
172   m_SingleMethod = 0;
173   m_SingleData = 0;
174   m_NumberOfThreads = this->GetGlobalDefaultNumberOfThreads();
175 }
176
177 MultiThreader::~MultiThreader()
178 {
179 #ifdef ITK_USE_SPROC
180   if (MultiThreader::m_ThreadArena != 0)
181     {
182     // close the file
183     close (MultiThreader::m_DevzeroFd);
184     // unmap the arena
185     usdetach (MultiThreader::m_ThreadArena);
186     
187     MultiThreader::m_ThreadArena= 0;
188     MultiThreader::m_Initialized= false;
189     MultiThreader::m_DevzeroFd= -1;
190     }
191 #endif
192 }
193
194 // Set the user defined method that will be run on NumberOfThreads threads
195 // when SingleMethodExecute is called.
196 void MultiThreader::SetSingleMethod( ThreadFunctionType f, void *data )
197 {
198   m_SingleMethod = f;
199   m_SingleData   = data;
200 }
201
202 // Set one of the user defined methods that will be run on NumberOfThreads
203 // threads when MultipleMethodExecute is called. This method should be
204 // called with index = 0, 1, ..,  NumberOfThreads-1 to set up all the
205 // required user defined methods
206 LEN void MultiThreader::SetMultipleMethod( int index, ThreadFunctionType f, void *data )
207
208   // You can only set the method for 0 through NumberOfThreads-1
209   if ( index >= m_NumberOfThreads )
210     {
211 LEN     itkExceptionMacro( << "Can't set method " << index << " with a thread count of " << m_NumberOfThreads );
212     }
213   else
214     {
215     m_MultipleMethod[index] = f;
216     m_MultipleData[index]   = data;
217     }
218 }
219
220 // Execute the method set as the SingleMethod on NumberOfThreads threads.
221 void MultiThreader::SingleMethodExecute()
222 {
223   int thread_loop;
224   ThreadProcessIDType process_id[ITK_MAX_THREADS];
225   
226   if ( !m_SingleMethod)
227     {
228     itkExceptionMacro( << "No single method set!" );
229     return;
230     }
231   
232   // obey the global maximum number of threads limit
233   if (m_GlobalMaximumNumberOfThreads &&
234       m_NumberOfThreads > m_GlobalMaximumNumberOfThreads)
235     {
236     m_NumberOfThreads = m_GlobalMaximumNumberOfThreads;
237     }
238   
239   // sproc needs special initialization logic prior to spawning
240   // threads
241 #ifdef ITK_USE_SPROC
242 IND # define STACK_SIZE 8*1024*1024
243   // set up the arena by the parent process ONLY if going to use more
244   // than 1 threads
245   if (!MultiThreader::m_Initialized && m_NumberOfThreads > 1)
246     {
247     MultiThreader::Initialize();
248     }
249   
250   struct rlimit64 rlpOld;
251   int code= getrlimit64 (RLIMIT_STACK, &rlpOld);
252   if (code != 0) itkExceptionMacro("getrlimit failed in Multithreader");
253   
254   struct rlimit64 rlpNew;
255   rlpNew.rlim_cur= STACK_SIZE;
256   rlpNew.rlim_max= rlpOld.rlim_max;
257   code= setrlimit64 (RLIMIT_STACK, &rlpNew);
258   if (code != 0) itkExceptionMacro("setrlimit failed in Multithreader");
259 #endif
260
261
262   // Spawn a set of threads through the SingleMethodProxy. Exceptions
263   // thrown from a thread will be caught by the SingleMethodProxy. A
264   // naive mechanism is in place for determining whether a thread
265   // threw an exception.
266   //
267   // Thanks to Hannu Helminen for suggestions on how to catch
268   // exceptions thrown by threads.
269   bool exceptionOccurred = false;
270   try
271     {
272     for (thread_loop = 1; thread_loop < m_NumberOfThreads; thread_loop++ )
273       {
274       m_ThreadInfoArray[thread_loop].UserData    = m_SingleData;
275       m_ThreadInfoArray[thread_loop].NumberOfThreads = m_NumberOfThreads;
276       m_ThreadInfoArray[thread_loop].ThreadFunction = m_SingleMethod;
277
278       process_id[thread_loop]
279         = this->DispatchSingleMethodThread(&m_ThreadInfoArray[thread_loop]);
280       }
281     }
282   catch (...)
283     {
284     // If creation of any thread failed, we must make sure that all
285     // threads are correctly cleaned
286     exceptionOccurred = true;
287     }
288   
289   // Now, the parent thread calls this->SingleMethod() itself
290   //
291   //
292   try
293     {
294     m_ThreadInfoArray[0].UserData = m_SingleData;
295     m_ThreadInfoArray[0].NumberOfThreads = m_NumberOfThreads;
296     m_SingleMethod((void *)(&m_ThreadInfoArray[0]));
297     }
298   catch ( ProcessAborted &excp )
299     {
300     // Need cleanup and rethrow ProcessAborted
301     // close down other threads
302     for (thread_loop = 1; thread_loop < m_NumberOfThreads; thread_loop++ )
303       {
304       try
305         {
306         this->WaitForSingleMethodThread(process_id[thread_loop]);
307         }
308       catch (...)
309         {
310         }
311       }
312     
313 #ifdef ITK_USE_SPROC
314     // reset the resource limits if using sproc
315     code= setrlimit64 (RLIMIT_STACK, &rlpOld);
316 #endif
317
318     // rethrow
319     throw excp;
320     }
321   catch (...)
322     {
323     // if this method fails, we must make sure all threads are
324     // correctly cleaned
325     exceptionOccurred = true;
326     }
327     
328   // The parent thread has finished this->SingleMethod() - so now it
329   // waits for each of the other processes to exit
330   for (thread_loop = 1; thread_loop < m_NumberOfThreads; thread_loop++ )
331     {
332     try
333       {
334       this->WaitForSingleMethodThread(process_id[thread_loop]);
335       if (m_ThreadInfoArray[thread_loop].ThreadExitCode
336           != ThreadInfoStruct::SUCCESS)
337         {
338         exceptionOccurred = true;
339         }
340       }
341     catch (...)
342       {
343       exceptionOccurred = true; 
344       }
345     }
346
347 #ifdef ITK_USE_SPROC
348   // reset the resource limits if using sproc
349   code= setrlimit64 (RLIMIT_STACK, &rlpOld);
350   if (code != 0)
351     {
352     itkExceptionMacro("setrlimit failed in Multithreader");
353     }
354 #endif
355   
356   if (exceptionOccurred)
357     {
358     itkExceptionMacro("Exception occurred during SingleMethodExecute");
359     }
360 }
361
362 void MultiThreader::MultipleMethodExecute()
363 {
364   int                thread_loop;
365   
366 #ifdef ITK_USE_WIN32_THREADS
367   DWORD              threadId;
368   HANDLE             process_id[ITK_MAX_THREADS];
369 #endif
370   
371 #ifdef ITK_USE_SPROC
372   siginfo_t          info_ptr;
373   int                process_id[ITK_MAX_THREADS];
374 #endif
375   
376 #ifdef ITK_USE_PTHREADS
377   pthread_t          process_id[ITK_MAX_THREADS];
378 #endif
379   
380   // obey the global maximum number of threads limit
381   if (m_GlobalMaximumNumberOfThreads &&
382       m_NumberOfThreads > m_GlobalMaximumNumberOfThreads)
383     {
384     m_NumberOfThreads = m_GlobalMaximumNumberOfThreads;
385     }
386   
387   for ( thread_loop = 0; thread_loop < m_NumberOfThreads; thread_loop++ )
388     {
389     if ( m_MultipleMethod[thread_loop] == (ThreadFunctionType)0)
390       {
391     itkExceptionMacro( << "No multiple method set for: " << thread_loop );
392     return;
393       }
394     }
395   
396   // We are using sproc (on SGIs), pthreads(on Suns), _beginthreadex
397   // on a PC or a single thread (the default)  
398   
399 #ifdef ITK_USE_WIN32_THREADS
400   // Using _beginthreadex on a PC
401   //
402   // We want to use _beginthreadex to start m_NumberOfThreads - 1 
403   // additional threads which will be used to call the NumberOfThreads-1
404   // methods defined in this->MultipleMethods[](). The parent thread
405   // will call m_MultipleMethods[NumberOfThreads-1]().  When it is done,
406   // it will wait for all the children to finish. 
407   //
408   // First, start up the m_NumberOfThreads-1 processes.  Keep track
409   // of their process ids for use later in the waitid call
410   for ( thread_loop = 1; thread_loop < m_NumberOfThreads; thread_loop++ )
411     {
412     m_ThreadInfoArray[thread_loop].UserData = 
413       m_MultipleData[thread_loop];
414     m_ThreadInfoArray[thread_loop].NumberOfThreads = m_NumberOfThreads;
415     
416     process_id[thread_loop] = (void *)
417       _beginthreadex(0, 0,
418 LEN                      (unsigned int (__stdcall *)(void *))m_MultipleMethod[thread_loop],
419                      ((void *)(&m_ThreadInfoArray[thread_loop])), 0,
420                      (unsigned int *)&threadId);
421     
422     if (process_id == 0)
423       {
424     itkExceptionMacro("Error in thread creation !!!");
425       } 
426     }
427   
428   // Now, the parent thread calls the last method itself
429   m_ThreadInfoArray[0].UserData = m_MultipleData[0];
430   m_ThreadInfoArray[0].NumberOfThreads = m_NumberOfThreads;
431   (m_MultipleMethod[0])((void *)(&m_ThreadInfoArray[0]) );
432   
433   // The parent thread has finished its method - so now it
434   // waits for each of the other processes (created with sproc) to
435   // exit
436   for ( thread_loop = 1; thread_loop < m_NumberOfThreads; thread_loop++ )
437     {
438     WaitForSingleObject(process_id[thread_loop], INFINITE);
439     }
440   
441   // close the threads
442   for ( thread_loop = 1; thread_loop < m_NumberOfThreads; thread_loop++ )
443     {
444     CloseHandle(process_id[thread_loop]);
445     }
446 #endif
447   
448 #ifdef ITK_USE_SPROC
449   // Using sproc() on an SGI
450   //
451   // We want to use sproc to start m_NumberOfThreads - 1 additional
452   // threads which will be used to call the NumberOfThreads-1 methods
453   // defined in m_MultipleMethods[](). The parent thread
454   // will call m_MultipleMethods[NumberOfThreads-1]().  When it is done,
455   // it will wait for all the children to finish. 
456   //
457   // First, start up the m_NumberOfThreads-1 processes.  Keep track
458   // of their process ids for use later in the waitid call
459   
460   if (!MultiThreader::m_Initialized && m_NumberOfThreads > 1)
461     {
462     MultiThreader::Initialize();
463     }
464   
465   struct rlimit64 rlpOld;
466   int code= getrlimit64 (RLIMIT_STACK, &rlpOld);
467   if (code != 0) itkExceptionMacro("getrlimit failed in Multithreader");
468   
469 IND # define STACK_SIZE 8*1024*1024
470   struct rlimit64 rlpNew;
471   rlpNew.rlim_cur= STACK_SIZE;
472   rlpNew.rlim_max= rlpOld.rlim_max;
473   code= setrlimit64 (RLIMIT_STACK, &rlpNew);
474   if (code != 0) itkExceptionMacro("setrlimit failed in Multithreader");
475   
476   for ( thread_loop = 1; thread_loop < m_NumberOfThreads; thread_loop++ )
477     {
478       m_ThreadInfoArray[thread_loop].UserData = m_MultipleData[thread_loop];
479       m_ThreadInfoArray[thread_loop].NumberOfThreads = m_NumberOfThreads;
480       process_id[thread_loop] = sproc( m_MultipleMethod[thread_loop], PR_SALL, 
481                ( (void *)(&m_ThreadInfoArray[thread_loop]) ) );
482     }
483   
484   // Now, the parent thread calls the last method itself
485   m_ThreadInfoArray[0].UserData = m_MultipleData[0];
486   m_ThreadInfoArray[0].NumberOfThreads = m_NumberOfThreads;
487   (m_MultipleMethod[0])((void *)(&m_ThreadInfoArray[0]) );
488   
489   // The parent thread has finished its method - so now it
490   // waits for each of the other processes (created with sproc) to
491   // exit
492   for ( thread_loop = 1; thread_loop < m_NumberOfThreads; thread_loop++ )
493     {
494       waitid( P_PID, (id_t) process_id[thread_loop], &info_ptr, WEXITED );
495     }
496   
497   code= setrlimit64 (RLIMIT_STACK, &rlpOld);
498   if (code != 0)
499     {
500     itkExceptionMacro("setrlimit failed in Multithreader");
501     }
502 #endif
503   
504 #ifdef ITK_USE_PTHREADS
505   // Using POSIX threads
506   //
507   // We want to use pthread_create to start m_NumberOfThreads - 1 
508   // additional
509   // threads which will be used to call the NumberOfThreads-1 methods
510   // defined in m_MultipleMethods[](). The parent thread
511   // will call m_MultipleMethods[NumberOfThreads-1]().  When it is done,
512   // it will wait for all the children to finish. 
513   //
514   // First, start up the m_NumberOfThreads-1 processes.  Keep track
515   // of their process ids for use later in the pthread_join call
516   
517   pthread_attr_t attr;
518   
519 #ifdef ITK_HP_PTHREADS
520   pthread_attr_create( &attr );
521 #else  
522   pthread_attr_init(&attr);
523 #ifndef __CYGWIN__
524   pthread_attr_setscope(&attr, PTHREAD_SCOPE_PROCESS);
525 #endif
526 #endif
527   
528   for ( thread_loop = 1; thread_loop < m_NumberOfThreads; thread_loop++ )
529     {
530     m_ThreadInfoArray[thread_loop].UserData = 
531       m_MultipleData[thread_loop];
532     m_ThreadInfoArray[thread_loop].NumberOfThreads = m_NumberOfThreads;
533 #ifdef ITK_HP_PTHREADS
534     pthread_create( &(process_id[thread_loop]),
535                     attr, m_MultipleMethod[thread_loop],  
536                     ( (void *)(&m_ThreadInfoArray[thread_loop]) ) );
537 #else
538     pthread_create( &(process_id[thread_loop]),
539 LEN                     &attr, reinterpret_cast<c_void_cast>(m_MultipleMethod[thread_loop]),  
540 IND ********************( (void *)(&m_ThreadInfoArray[thread_loop]) ) );
541 #endif
542     }
543   
544   // Now, the parent thread calls the last method itself
545   m_ThreadInfoArray[0].UserData = m_MultipleData[0];
546   m_ThreadInfoArray[0].NumberOfThreads = m_NumberOfThreads;
547   (m_MultipleMethod[0])((void *)(&m_ThreadInfoArray[0]) );
548   
549   // The parent thread has finished its method - so now it
550   // waits for each of the other processes to exit
551   for ( thread_loop = 1; thread_loop < m_NumberOfThreads; thread_loop++ )
552     {
553     pthread_join( process_id[thread_loop], 0 );
554     }
555 #endif
556   
557 #ifndef ITK_USE_WIN32_THREADS
558 #ifndef ITK_USE_SPROC
559 #ifndef ITK_USE_PTHREADS
560   // There is no multi threading, so there is only one thread.
561   m_ThreadInfoArray[0].UserData    = m_MultipleData[0];
562   m_ThreadInfoArray[0].NumberOfThreads = m_NumberOfThreads;
563   (m_MultipleMethod[0])( (void *)(&m_ThreadInfoArray[0]) );
564 #endif
565 #endif
566 #endif
567 }
568
569 int MultiThreader::SpawnThread( ThreadFunctionType f, void *UserData )
570 {
571   int id;
572   
573 #ifdef ITK_USE_WIN32_THREADS
574   DWORD              threadId;
575 #endif
576   
577   id = 0;
578   
579   while ( id < ITK_MAX_THREADS )
580     {
581     if ( ! m_SpawnedThreadActiveFlagLock[id]  )
582       {
583     m_SpawnedThreadActiveFlagLock[id] = MutexLock::New();
584       }
585     m_SpawnedThreadActiveFlagLock[id]->Lock();
586     if (m_SpawnedThreadActiveFlag[id] == 0)
587       {
588 IND ****// We've got a useable thread id, so grab it
589 IND ****m_SpawnedThreadActiveFlag[id] = 1;
590 IND ****m_SpawnedThreadActiveFlagLock[id]->Unlock();
591 IND ****break;
592       }
593     m_SpawnedThreadActiveFlagLock[id]->Unlock();
594     
595     id++;
596     }
597   
598   if ( id >= ITK_MAX_THREADS )
599     {
600     itkExceptionMacro( << "You have too many active threads!" );
601     return -1;
602     }
603   
604   m_SpawnedThreadInfoArray[id].UserData        = UserData;
605   m_SpawnedThreadInfoArray[id].NumberOfThreads = 1;
606   m_SpawnedThreadInfoArray[id].ActiveFlag = &m_SpawnedThreadActiveFlag[id];
607 LEN   m_SpawnedThreadInfoArray[id].ActiveFlagLock = m_SpawnedThreadActiveFlagLock[id];
608   
609   // We are using sproc (on SGIs), pthreads(on Suns or HPs), 
610   // _beginthreadex (on win32), or generating an error  
611   
612 #ifdef ITK_USE_WIN32_THREADS
613   // Using _beginthreadex on a PC
614   //
615   m_SpawnedThreadProcessID[id] = (void *)
616     _beginthreadex(0, 0, (unsigned int (__stdcall *)(void *))f, 
617                    ((void *)(&m_SpawnedThreadInfoArray[id])), 0,
618                    (unsigned int *)&threadId);
619   if (m_SpawnedThreadProcessID[id] == 0)
620     {
621     itkExceptionMacro("Error in thread creation !!!");
622     } 
623 #endif
624   
625 #ifdef ITK_USE_SPROC
626   // Using sproc() on an SGI
627   //
628 LEN   m_SpawnedThreadProcessID[id] = sproc( f, PR_SADDR, ( (void *)(&m_SpawnedThreadInfoArray[id]) ) );
629   
630 #endif
631   
632 #ifdef ITK_USE_PTHREADS
633   // Using POSIX threads
634   //
635   pthread_attr_t attr;
636   
637 #ifdef ITK_HP_PTHREADS
638   pthread_attr_create( &attr );
639 #else  
640   pthread_attr_init(&attr);
641 #ifndef __CYGWIN__
642   pthread_attr_setscope(&attr, PTHREAD_SCOPE_PROCESS);
643 #endif
644 #endif
645   
646 #ifdef ITK_HP_PTHREADS
647   pthread_create( &(m_SpawnedThreadProcessID[id]),
648                   attr, reinterpret_cast<c_void_cast>(f),  
649 IND ******************( (void *)(&m_SpawnedThreadInfoArray[id]) ) );
650 IND #else
651   pthread_create( &(m_SpawnedThreadProcessID[id]),
652 IND ******************&attr, reinterpret_cast<c_void_cast>(f),  
653 IND ******************( (void *)(&m_SpawnedThreadInfoArray[id]) ) );
654 #endif
655   
656 #endif
657   
658 #ifndef ITK_USE_WIN32_THREADS
659 #ifndef ITK_USE_SPROC
660 #ifndef ITK_USE_PTHREADS
661   // There is no multi threading, so there is only one thread.
662   // This won't work - so give an error message.
663 LEN   itkExceptionMacro( << "Cannot spawn thread in a single threaded environment!" );
664   m_SpawnedThreadActiveFlagLock[id] = 0;
665   id = -1;
666 #endif
667 #endif
668 #endif
669   
670   return id;
671 }
672
673 void MultiThreader::TerminateThread( int ThreadID )
674 {
675   if ( !m_SpawnedThreadActiveFlag[ThreadID] )
676     {
677     return;
678     }
679   
680   m_SpawnedThreadActiveFlagLock[ThreadID]->Lock();
681   m_SpawnedThreadActiveFlag[ThreadID] = 0;
682   m_SpawnedThreadActiveFlagLock[ThreadID]->Unlock();
683   
684 #ifdef ITK_USE_WIN32_THREADS
685   WaitForSingleObject(m_SpawnedThreadProcessID[ThreadID], INFINITE);
686   CloseHandle(m_SpawnedThreadProcessID[ThreadID]);
687 #endif
688   
689 #ifdef ITK_USE_SPROC
690   siginfo_t info_ptr;
691   
692   waitid( P_PID, (id_t) m_SpawnedThreadProcessID[ThreadID], 
693 IND **********&info_ptr, WEXITED );
694 #endif
695   
696 #ifdef ITK_USE_PTHREADS
697   pthread_join( m_SpawnedThreadProcessID[ThreadID], 0 );
698 #endif
699   
700 #ifndef ITK_USE_WIN32_THREADS
701 #ifndef ITK_USE_SPROC
702 #ifndef ITK_USE_PTHREADS
703   // There is no multi threading, so there is only one thread.
704   // This won't work - so give an error message.
705 LEN   itkExceptionMacro(<< "Cannot terminate thread in single threaded environment!");
706 #endif
707 #endif
708 #endif
709   
710   m_SpawnedThreadActiveFlagLock[ThreadID] = 0;
711   m_SpawnedThreadActiveFlagLock[ThreadID] = 0;
712 }
713
714 // Print method for the multithreader
715 void MultiThreader::PrintSelf(std::ostream& os, Indent indent) const
716 {
717   Superclass::PrintSelf(os,indent); 
718   
719   os << indent << "Thread Count: " << m_NumberOfThreads << "\n";
720   os << indent << "Global Maximum Number Of Threads: " << 
721     m_GlobalMaximumNumberOfThreads << std::endl;
722 }
723
724 ITK_THREAD_RETURN_TYPE
725 MultiThreader
726 ::SingleMethodProxy( void *arg )
727 {
728   // grab the ThreadInfoStruct originally prescribed
729   MultiThreader::ThreadInfoStruct
730     *threadInfoStruct
731     = reinterpret_cast<MultiThreader::ThreadInfoStruct *>(arg);
732
733   // execute the user specified threader callback, catching any exceptions
734   try
735     {
736     (*threadInfoStruct->ThreadFunction)(threadInfoStruct);
737     threadInfoStruct->ThreadExitCode
738 IND ******= MultiThreader::ThreadInfoStruct::SUCCESS;
739     }
740   catch (ProcessAborted &)
741     {
742     threadInfoStruct->ThreadExitCode
743 IND ******= MultiThreader::ThreadInfoStruct::ITK_PROCESS_ABORTED_EXCEPTION;
744     }
745   catch (ExceptionObject &)
746     {
747     threadInfoStruct->ThreadExitCode
748 IND ******= MultiThreader::ThreadInfoStruct::ITK_EXCEPTION;
749     }
750   catch (std::exception &)
751     {
752     threadInfoStruct->ThreadExitCode
753 IND ******= MultiThreader::ThreadInfoStruct::STD_EXCEPTION;
754     }
755   catch (...)
756     {
757     threadInfoStruct->ThreadExitCode
758 IND ******= MultiThreader::ThreadInfoStruct::UNKNOWN;
759     }
760
761   return ITK_THREAD_RETURN_VALUE;
762 }
763
764 void
765 MultiThreader
766 ::WaitForSingleMethodThread(ThreadProcessIDType threadHandle)
767 {
768 #ifdef ITK_USE_WIN32_THREADS
769   // Using _beginthreadex on a PC
770   WaitForSingleObject(threadHandle, INFINITE);
771   CloseHandle(threadHandle);
772 #endif
773
774 #ifdef ITK_USE_SPROC
775   // Using sproc() on an SGI
776   siginfo_t          info_ptr;
777   waitid( P_PID, (id_t) threadHandle, &info_ptr, WEXITED );
778 #endif
779
780 #ifdef ITK_USE_PTHREADS
781   // Using POSIX threads
782   if ( pthread_join( threadHandle, 0 ) )
783     {
784     itkExceptionMacro(<< "Unable to join thread.");
785     }
786 #endif      
787
788
789 #ifndef ITK_USE_WIN32_THREADS
790 #ifndef ITK_USE_SPROC
791 #ifndef ITK_USE_PTHREADS
792     // No threading library specified.  Do nothing.  No joining or waiting
793     // necessary.
794 #endif
795 #endif
796 #endif
797     
798 }
799
800
801 EML
802 ThreadProcessIDType
803 MultiThreader
804 ::DispatchSingleMethodThread(MultiThreader::ThreadInfoStruct *threadInfo)
805 {
806 #ifdef ITK_USE_WIN32_THREADS
807   // Using _beginthreadex on a PC
808   DWORD threadId;
809   HANDLE threadHandle =  (HANDLE)_beginthreadex(0, 0,
810                (unsigned int (__stdcall *)(void *))this->SingleMethodProxy, 
811 IND ***************((void *)threadInfo), 0, (unsigned int *)&threadId);
812   if (threadHandle == NULL)
813     {
814     itkExceptionMacro("Error in thread creation !!!");
815     } 
816   return threadHandle;
817 #endif
818
819   
820 #ifdef ITK_USE_SPROC
821   // Using sproc() on an SGI
822 IND ****pid_t threadHandle = 
823 IND ******sproc( this->SingleMethodProxy, PR_SALL, 
824        reinterpret_cast<void *>(threadInfo));
825 IND ****if ( threadHandle == -1)
826 IND ******{
827 IND ******itkExceptionMacro("sproc call failed. Code: " << errno << std::endl);
828       }
829     return threadHandle;
830 #endif
831
832
833     
834 #ifdef ITK_USE_PTHREADS
835   // Using POSIX threads
836     pthread_attr_t attr;
837     pthread_t threadHandle;
838
839 #ifdef ITK_HP_PTHREADS
840     pthread_attr_create( &attr );
841 #else  
842     pthread_attr_init(&attr);
843 #if !defined(__CYGWIN__)
844     pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM);
845 #endif
846 #endif
847
848 #ifdef ITK_HP_PTHREADS
849     pthread_create( &threadHandle,
850         attr, reinterpret_cast<c_void_cast>(this->SingleMethodProxy),  
851 IND ********reinterpret_cast<void *>(threadInfo));
852 IND #else
853 IND ****int                threadError;
854 IND ****threadError =
855 LEN,IND ******pthread_create( &threadHandle, &attr, reinterpret_cast<c_void_cast>(this->SingleMethodProxy),  
856 IND **********reinterpret_cast<void *>(threadInfo));
857 IND ****if (threadError != 0)
858 IND ******{
859 LEN,IND ******itkExceptionMacro(<< "Unable to create a thread.  pthread_create() returned "
860 IND ********************<< threadError);
861 IND ******}
862 #endif
863 IND ****return threadHandle;
864 #endif      
865
866
867 #ifndef ITK_USE_WIN32_THREADS
868 #ifndef ITK_USE_SPROC
869 #ifndef ITK_USE_PTHREADS
870 IND ****// No threading library specified.  Do nothing.  The computation
871 IND ****// will be run by the main execution thread.
872 #endif
873 #endif
874 #endif
875     
876 }
877
878
879 // end namespace itk
880

Generated by KWStyle 1.0b on Tuesday January,17 at 02:14:26PM
© Kitware Inc.