OTB  10.0.0
Orfeo Toolbox
otbMacro.h
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2005-2024 Centre National d'Etudes Spatiales (CNES)
3  *
4  * This file is part of Orfeo Toolbox
5  *
6  * https://www.orfeo-toolbox.org/
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  * http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  */
20 
21 
28 #ifndef otbMacro_h
29 #define otbMacro_h
30 
31 #include "itkMacro.h"
32 #include "itkObject.h"
33 #include "itkThreadSupport.h"
34 #include "otbConfigure.h"
35 #include "otbLogger.h"
36 
43 namespace otb
44 {
45 } // end namespace otb - this is here for documentation purposes
46 /* ITK 5.0 uses a different threading model compared to ITK 4.x.
47  * This has a significant impact on OTB as we make heavy use of itk filters.
48  * DynamicThreadedGenerateData() is the newer variant without threadId,
49  * and is the preferred signature, which is called by default. This
50  * variant can split the requested region into different number of
51  * pieces depending on current multi-processing load, which allows
52  * better load balancing. The non-dynamic (also known as classic)
53  * ThreadedGenerateData() signature has threadId, and number of pieces
54  * to be split into is known in advance. It is activated by calling
55  * this->DynamicMultiThreadingOff(); in derived class constructor.
56  *
57  * OTB uses ThreadedGenerateData() with threadId and thus required
58  * to call this->DynamicMultiThreadingOff(); in filter's constructor.
59  *
60  * OTB_DISABLE_DYNAMIC_MT is a simple macro that insert this
61  * function call *IF* itk version used is 5.0 or above.
62  * This macro expands to empty when OTB is built with ITK 4.x and
63  * this ease from ITK 4.x to ITK 5.x. Ideally ThreadedGenerateData() function
64  * everywhere in OTB must be replace with DynamicThreadedGenerateData().
65  * This for sure is not a glorified sed command. Usage of function parameter
66  * threadId (and progress reporter) must be removed as well.
67  *
68  * It also leads us into a situation that OTB will no longer work with ITK 4.x.
69  * We cannot break that until ITK 5.0 is available on all platforms and is well tested.
70  * As time of writing this patch ITK 5.0 is in alpha release.
71  * Eventually OTB can move up in direction where it is requires ITK 5.0 or.
72  * But until things are resolved this macro based compatibility must stay.
73  *
74  * Finally please note that OTB_DISABLE_DYNAMIC_MT does not disable multithreading.
75  * Method or macro name can sometimes cause confusion when reading code.
76  *
77  * sample run-time exception:
78  * =========================
79  * 2018-06-04 15:30:09 (DEBUG): Caught itk::ExceptionObject during application execution:
80  * 2018-06-04 15:30:09 (DEBUG): /usr/src/ports/itk/Modules/Core/Common/src/itkPoolMultiThreader.cxx:202:
81  * itk::ERROR: PoolMultiThreader(0xabad1dea): Exception occurred during SingleMethodExecute
82  * /home/rashad/local/include/ITK-5.0/itkImageSource.hxx:276:
83  * itk::ERROR: ShiftScaleImageFilter(0xabad1deaff): Subclass should override this method!!!
84  * If old behavior is desired invoke this->DynamicMultiThreadingOff(); before Update() is called. The best place is in class constructor.
85  */
86 #define OTB_DISABLE_DYNAMIC_MT this->DynamicMultiThreadingOff();
88 
89 /*
90 //ITK_THREAD_RETURN_TYPE and ITK_THREAD_RETURN_VALUE bas been changed in ITK5 (master)
91 // we need to re-exposed to the global namespace to keep the
92 // use of these items consistent.
93 #if ITK_VERSION_MAJOR > 4
94 #define ITK_THREAD_RETURN_TYPE itk::ITK_THREAD_RETURN_TYPE
95 #define ITK_THREAD_RETURN_VALUE itk::ITK_THREAD_RETURN_DEFAULT_VALUE
96 #endif
97 */
98 
99 #define otbFileContext(x) << "file " __FILE__ ", line " << __LINE__ << ", " x
100 
101 #define otbClassContext(x) << this->GetNameOfClass() << " (" << this << "): " x
102 
103 // Beware that to log to CRITICAL level, level should be passed as "Error"
104 #define otbLogMacro(level, msg) \
105  { \
106  std::ostringstream itkmsg; \
107  itkmsg msg << "\n"; \
108  otb::Logger::Instance()->level(itkmsg.str().c_str()); \
109  }
110 
111 
112 // Re-definition of old log macros to use the otbLogMacro
113 #define otbDebugMacro(x) otbLogMacro(Debug, otbFileContext(otbClassContext(x)))
114 #define otbMsgDebugMacro(x) otbLogMacro(Debug, otbFileContext(x))
115 #define otbGenericMsgDebugMacro(x) otbLogMacro(Debug, x)
116 #define otbMsgDevMacro(x) otbLogMacro(Debug, otbFileContext(x))
117 #define otbWarningMacro(x) otbLogMacro(Warning, otbFileContext(otbClassContext(x)))
118 #define otbGenericWarningMacro(x) otbLogMacro(Warning, otbFileContext(x))
119 #define otbGenericMsgTestingMAcro(x) otbLogMacro(Info, "[testing] " << x)
120 
124 #define otbControlConditionTestMacro(condition, message) \
125  { \
126  if ((condition)) \
127  itkGenericExceptionMacro(<< message); \
128  }
129 
131 #define otbSetObjectMemberMacro(object, name, type) \
132  virtual void Set##name(const type _arg) \
133  { \
134  itkDebugMacro("setting member " #name " to " << _arg); \
135  this->m_##object->Set##name(_arg); \
136  this->Modified(); \
137  }
139 
141 #define otbGetObjectMemberMacro(object, name, type) \
142  virtual type Get##name() \
143  { \
144  itkDebugMacro("returning " << #name " of " << this->m_##object->Get##name()); \
145  return this->m_##object->Get##name(); \
146  }
148 
152 #define otbGetObjectMemberConstMacro(object, name, type) \
153  virtual type Get##name() const \
154  { \
155  itkDebugMacro("returning " << #name " of " << this->m_##object->Get##name()); \
156  return this->m_##object->Get##name(); \
157  }
159 
164 #define otbGetObjectMemberConstReferenceMacro(object, name, type) \
165  virtual const type& Get##name() const \
166  { \
167  itkDebugMacro("returning " << #name " of " << this->m_##object->Get##name()); \
168  return this->m_##object->Get##name(); \
169  }
171 
175 #define otbTestingCheckValidCommand(command) \
176  { \
177  try \
178  { \
179  command; \
180  } \
181  catch (const std::exception&) \
182  { \
183  throw; \
184  } \
185  catch (...) \
186  { \
187  std::ostringstream message; \
188  message << "otb::ERROR Unknown error while running " << #command << " (catch(...) )"; \
189  ::itk::ExceptionObject e_(__FILE__, __LINE__, message.str(), ITK_LOCATION); \
190  throw e_; \
191  } \
192  std::cout << " Checking valid command " << #command " ok." << std::endl; \
193  }
195 
196 #define otbGenericExceptionMacro(T, x) \
197  { \
198  std::ostringstream message; \
199  message << "otb::ERROR: " x; \
200  T e_(__FILE__, __LINE__, message.str(), ITK_LOCATION); \
201  throw e_; \
202  }
203 
204 #define otbTestingCheckNotValidCommand(command) \
205  { \
206  int result(1); \
207  try \
208  { \
209  command; \
210  } \
211  catch (std::bad_alloc & err) \
212  { \
213  throw err; \
214  } \
215  catch (itk::ExceptionObject&) \
216  { \
217  std::cout << "Checking not valid Command " << #command " ok." << std::endl; \
218  result = 0; \
219  } \
220  catch (const std::exception& stde) \
221  { \
222  throw stde; \
223  } \
224  catch (...) \
225  { \
226  std::ostringstream message; \
227  message << "otb::ERROR Unknown error while running " << #command << " (catch(...) )"; \
228  ::itk::ExceptionObject e_(__FILE__, __LINE__, message.str(), ITK_LOCATION); \
229  throw e_; \
230  } \
231  if (result == 1) \
232  { \
233  std::ostringstream message; \
234  message << "otb::ERROR: " << #command << " should be throwing an exception."; \
235  ::itk::ExceptionObject e_(__FILE__, __LINE__, message.str(), ITK_LOCATION); \
236  throw e_; \
237  } \
238  }
239 
240 #define otbUnusedMacro(x) \
241  do \
242  { \
243  (void)sizeof(x); \
244  } while (0)
245 
246 //
247 // Unused variable warnings in Debug/Release management.
248 // assert() macros are defined on NDEBUG and nothing else => stay standard and use NDEBUG instead of OTB_DEBUG
249 #if !defined(NDEBUG)
250 #define otbUseInDebug(name) name
251 #define otbUseInRelease(name)
252 #else // NDEBUG
253 #define otbUseInDebug(name)
254 #define otbUseInRelease(name) name
255 #endif // NDEBUG
256 
257 
258 // MSVC doesn't have __has_attribute, let's silence it!
259 #ifndef __has_attribute
260 # define __has_attribute(attr) 0
261 #endif
262 
263 #if __has_cpp_attribute(fallthrough)
264 # define OTB_FALLTHROUGH [[fallthrough]]
265 #elif __has_attribute(fallthrough)
266 # define OTB_FALLTHROUGH __attribute__((fallthrough))
267 #else
268 # define OTB_FALLTHROUGH
269 #endif
270 
271 #endif // end of otbMacro.h
The "otb" namespace contains all Orfeo Toolbox (OTB) classes.