1 /*=========================================================================
2  *
3  *  Copyright Insight Software Consortium
4  *
5  *  Licensed under the Apache License, Version 2.0 (the "License");
6  *  you may not use this file except in compliance with the License.
7  *  You may obtain a copy of the License at
8  *
9  *         http://www.apache.org/licenses/LICENSE-2.0.txt
10  *
11  *  Unless required by applicable law or agreed to in writing, software
12  *  distributed under the License is distributed on an "AS IS" BASIS,
13  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  *  See the License for the specific language governing permissions and
15  *  limitations under the License.
16  *
17  *=========================================================================*/
18 #ifndef itkThreadSupport_h
19 #define itkThreadSupport_h
20 
21 #include <cstdlib>
22 
23 // This implementation uses a routine called SignalObjectAndWait()
24 // which is only defined on WinNT 4.0 or greater systems.  We need to
25 // define this symbol in order to get the prototype for the
26 // routine. This needs to be done before we load any system headers.
27 #ifdef ITK_USE_WIN32_THREADS
28 #ifndef _WIN32_WINNT
29 #define _WIN32_WINNT 0x0501 //TBB 4.4 requires WinXP (0x0501 or greater)
30 #endif
31 #endif
32 
33 #if defined(ITK_USE_PTHREADS)
34 #include <pthread.h>
35 #elif defined(ITK_USE_WIN32_THREADS)
36 #include "itkWindows.h"
37 #include <winbase.h>
38 #endif
39 #include "itkConfigure.h"
40 
41 
42 namespace itk
43 {
44   /** Platform specific type alias for simple types
45    */
46 #if defined(ITK_USE_PTHREADS)
47   constexpr std::size_t ITK_MAX_THREADS = ITK_DEFAULT_MAX_THREADS;
48   using MutexType = pthread_mutex_t;
49   using FastMutexType = pthread_mutex_t;
50   using ThreadFunctionType = void *(*)(void *);
51   using ThreadProcessIdType = pthread_t;
52   constexpr ThreadProcessIdType ITK_DEFAULT_THREAD_ID = 0;
53   using ITK_THREAD_RETURN_TYPE = void *;
54   constexpr ITK_THREAD_RETURN_TYPE ITK_THREAD_RETURN_DEFAULT_VALUE = NULL; /* This is from a c library, and always needs to be NULL, not nullptr */
55   using itk::ITK_THREAD_RETURN_DEFAULT_VALUE;  //We need this out of the itk namespace for #define to work below
56   using ITK_THREAD_RETURN_FUNCTION_CALL_CONVENTION = itk::ITK_THREAD_RETURN_TYPE;
57 #elif defined(ITK_USE_WIN32_THREADS)
58 
59   constexpr std::size_t ITK_MAX_THREADS = ITK_DEFAULT_MAX_THREADS;
60   using MutexType = HANDLE;
61   using FastMutexType = CRITICAL_SECTION;
62   typedef unsigned(__stdcall * ThreadFunctionType)(void *);
63   using ThreadProcessIdType = HANDLE;
64   static const ThreadProcessIdType ITK_DEFAULT_THREAD_ID = INVALID_HANDLE_VALUE;
65   using ITK_THREAD_RETURN_TYPE = unsigned;
66   constexpr ITK_THREAD_RETURN_TYPE ITK_THREAD_RETURN_DEFAULT_VALUE = 0;
67   // WINAPI expands to __stdcall which specifies a function call convention and has little no meaning on variable declarations
68   #define ITK_THREAD_RETURN_FUNCTION_CALL_CONVENTION itk::ITK_THREAD_RETURN_TYPE __stdcall
69 #else
70 
71   constexpr std::size_t ITK_MAX_THREADS = 1;
72   using MutexType = int;
73   using FastMutexType = int;
74   typedef void ( *ThreadFunctionType )(void *);
75   using ThreadProcessIdType = int;
76   constexpr ThreadProcessIdType ITK_DEFAULT_THREAD_ID = 0;
77   using ITK_THREAD_RETURN_TYPE = void;
78   #define ITK_THREAD_RETURN_DEFAULT_VALUE
79   using ITK_THREAD_RETURN_FUNCTION_CALL_CONVENTION = itk::ITK_THREAD_RETURN_TYPE;
80 #endif
81 
82 
83   /** Platform specific Conditional Variable type alias
84    */
85 #if defined(ITK_USE_PTHREADS)
86   typedef struct {
87   pthread_cond_t m_ConditionVariable;
88   } ConditionVariableType;
89 #elif defined(ITK_USE_WIN32_THREADS)
90   typedef struct {
91   int m_NumberOfWaiters;                   // number of waiting threads
92   CRITICAL_SECTION m_NumberOfWaitersLock;  // Serialize access to
93                                            // m_NumberOfWaiters
94 
95   HANDLE m_Semaphore;                      // Semaphore to queue threads
96   HANDLE m_WaitersAreDone;                 // Auto-reset event used by the
97                                            // broadcast/signal thread to
98                                            // wait for all the waiting
99                                            // threads to wake up and
100                                            // release the semaphore
101 
102   int m_WasBroadcast;                      // Used as boolean. Keeps track of whether
103                                            // we were broadcasting or signaling
104   } ConditionVariableType;
105 #else
106   using ConditionVariableType = struct { };
107 #endif
108 
109 }
110 
111 // Compile-time conditional code for different threading models
112 // require that some items are #defines (always global scope) or
113 // can sometimes be rigorously typed.  When rigorously typed,
114 // we need to re-exposed to the global namespace to keep the
115 // use of these items consistent.
116 #if defined(ITK_USE_PTHREADS)
117 using itk::ITK_THREAD_RETURN_FUNCTION_CALL_CONVENTION;
118 using itk::ITK_THREAD_RETURN_DEFAULT_VALUE;  //We need this out of the itk namespace for #define to work below
119 #elif defined(ITK_USE_WIN32_THREADS)
120 using itk::ITK_THREAD_RETURN_DEFAULT_VALUE;  //We need this out of the itk namespace for #define to work below
121 #else
122 using itk::ITK_THREAD_RETURN_FUNCTION_CALL_CONVENTION;
123 #endif
124 
125 // For backwards compatiblity
126 #if ! defined ( ITK_FUTURE_LEGACY_REMOVE )
127   using itk::ITK_MAX_THREADS;
128   using itk::ITK_DEFAULT_THREAD_ID;
129 #endif
130 
131 #endif
132