tbb_stddef.h 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565
  1. /*
  2. Copyright (c) 2005-2020 Intel Corporation
  3. Licensed under the Apache License, Version 2.0 (the "License");
  4. you may not use this file except in compliance with the License.
  5. You may obtain a copy of the License at
  6. http://www.apache.org/licenses/LICENSE-2.0
  7. Unless required by applicable law or agreed to in writing, software
  8. distributed under the License is distributed on an "AS IS" BASIS,
  9. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. See the License for the specific language governing permissions and
  11. limitations under the License.
  12. */
  13. #ifndef __TBB_tbb_stddef_H
  14. #define __TBB_tbb_stddef_H
  15. // Marketing-driven product version
  16. #define TBB_VERSION_MAJOR 2020
  17. #define TBB_VERSION_MINOR 3
  18. // Engineering-focused interface version
  19. #define TBB_INTERFACE_VERSION 11103
  20. #define TBB_INTERFACE_VERSION_MAJOR TBB_INTERFACE_VERSION/1000
  21. // The oldest major interface version still supported
  22. // To be used in SONAME, manifests, etc.
  23. #define TBB_COMPATIBLE_INTERFACE_VERSION 2
  24. #define __TBB_STRING_AUX(x) #x
  25. #define __TBB_STRING(x) __TBB_STRING_AUX(x)
  26. // We do not need defines below for resource processing on windows
  27. #if !defined RC_INVOKED
  28. // Define groups for Doxygen documentation
  29. /**
  30. * @defgroup algorithms Algorithms
  31. * @defgroup containers Containers
  32. * @defgroup memory_allocation Memory Allocation
  33. * @defgroup synchronization Synchronization
  34. * @defgroup timing Timing
  35. * @defgroup task_scheduling Task Scheduling
  36. */
  37. // Simple text that is displayed on the main page of Doxygen documentation.
  38. /**
  39. * \mainpage Main Page
  40. *
  41. * Click the tabs above for information about the
  42. * - <a href="./modules.html">Modules</a> (groups of functionality) implemented by the library
  43. * - <a href="./annotated.html">Classes</a> provided by the library
  44. * - <a href="./files.html">Files</a> constituting the library.
  45. * .
  46. * Please note that significant part of TBB functionality is implemented in the form of
  47. * template functions, descriptions of which are not accessible on the <a href="./annotated.html">Classes</a>
  48. * tab. Use <a href="./modules.html">Modules</a> or <a href="./namespacemembers.html">Namespace/Namespace Members</a>
  49. * tabs to find them.
  50. *
  51. * Additional pieces of information can be found here
  52. * - \subpage concepts
  53. * .
  54. */
  55. /** \page concepts TBB concepts
  56. A concept is a set of requirements to a type, which are necessary and sufficient
  57. for the type to model a particular behavior or a set of behaviors. Some concepts
  58. are specific to a particular algorithm (e.g. algorithm body), while other ones
  59. are common to several algorithms (e.g. range concept).
  60. All TBB algorithms make use of different classes implementing various concepts.
  61. Implementation classes are supplied by the user as type arguments of template
  62. parameters and/or as objects passed as function call arguments. The library
  63. provides predefined implementations of some concepts (e.g. several kinds of
  64. \ref range_req "ranges"), while other ones must always be implemented by the user.
  65. TBB defines a set of minimal requirements each concept must conform to. Here is
  66. the list of different concepts hyperlinked to the corresponding requirements specifications:
  67. - \subpage range_req
  68. - \subpage parallel_do_body_req
  69. - \subpage parallel_for_body_req
  70. - \subpage parallel_reduce_body_req
  71. - \subpage parallel_scan_body_req
  72. - \subpage parallel_sort_iter_req
  73. **/
  74. // tbb_config.h should be included the first since it contains macro definitions used in other headers
  75. #include "tbb_config.h"
  76. #if _MSC_VER >=1400
  77. #define __TBB_EXPORTED_FUNC __cdecl
  78. #define __TBB_EXPORTED_METHOD __thiscall
  79. #else
  80. #define __TBB_EXPORTED_FUNC
  81. #define __TBB_EXPORTED_METHOD
  82. #endif
  83. #if __INTEL_COMPILER || _MSC_VER
  84. #define __TBB_NOINLINE(decl) __declspec(noinline) decl
  85. #elif __GNUC__
  86. #define __TBB_NOINLINE(decl) decl __attribute__ ((noinline))
  87. #else
  88. #define __TBB_NOINLINE(decl) decl
  89. #endif
  90. #if __TBB_NOEXCEPT_PRESENT
  91. #define __TBB_NOEXCEPT(expression) noexcept(expression)
  92. #else
  93. #define __TBB_NOEXCEPT(expression)
  94. #endif
  95. #include <cstddef> /* Need size_t and ptrdiff_t */
  96. #if _MSC_VER
  97. #define __TBB_tbb_windef_H
  98. #include "internal/_tbb_windef.h"
  99. #undef __TBB_tbb_windef_H
  100. #endif
  101. #if !defined(_MSC_VER) || _MSC_VER>=1600
  102. #include <stdint.h>
  103. #endif
  104. //! Type for an assertion handler
  105. typedef void(*assertion_handler_type)( const char* filename, int line, const char* expression, const char * comment );
  106. #if __TBBMALLOC_BUILD
  107. namespace rml { namespace internal {
  108. #define __TBB_ASSERT_RELEASE(predicate,message) ((predicate)?((void)0) : rml::internal::assertion_failure(__FILE__,__LINE__,#predicate,message))
  109. #else
  110. namespace tbb {
  111. #define __TBB_ASSERT_RELEASE(predicate,message) ((predicate)?((void)0) : tbb::assertion_failure(__FILE__,__LINE__,#predicate,message))
  112. #endif
  113. //! Set assertion handler and return previous value of it.
  114. assertion_handler_type __TBB_EXPORTED_FUNC set_assertion_handler( assertion_handler_type new_handler );
  115. //! Process an assertion failure.
  116. /** Normally called from __TBB_ASSERT macro.
  117. If assertion handler is null, print message for assertion failure and abort.
  118. Otherwise call the assertion handler. */
  119. void __TBB_EXPORTED_FUNC assertion_failure( const char* filename, int line, const char* expression, const char* comment );
  120. #if __TBBMALLOC_BUILD
  121. }} // namespace rml::internal
  122. #else
  123. } // namespace tbb
  124. #endif
  125. #if TBB_USE_ASSERT
  126. //! Assert that predicate is true.
  127. /** If predicate is false, print assertion failure message.
  128. If the comment argument is not NULL, it is printed as part of the failure message.
  129. The comment argument has no other effect. */
  130. #define __TBB_ASSERT(predicate,message) __TBB_ASSERT_RELEASE(predicate,message)
  131. #define __TBB_ASSERT_EX __TBB_ASSERT
  132. #else /* !TBB_USE_ASSERT */
  133. //! No-op version of __TBB_ASSERT.
  134. #define __TBB_ASSERT(predicate,comment) ((void)0)
  135. //! "Extended" version is useful to suppress warnings if a variable is only used with an assert
  136. #define __TBB_ASSERT_EX(predicate,comment) ((void)(1 && (predicate)))
  137. #endif /* !TBB_USE_ASSERT */
  138. //! The namespace tbb contains all components of the library.
  139. namespace tbb {
  140. namespace internal {
  141. #if _MSC_VER && _MSC_VER<1600
  142. typedef __int8 int8_t;
  143. typedef __int16 int16_t;
  144. typedef __int32 int32_t;
  145. typedef __int64 int64_t;
  146. typedef unsigned __int8 uint8_t;
  147. typedef unsigned __int16 uint16_t;
  148. typedef unsigned __int32 uint32_t;
  149. typedef unsigned __int64 uint64_t;
  150. #else /* Posix */
  151. using ::int8_t;
  152. using ::int16_t;
  153. using ::int32_t;
  154. using ::int64_t;
  155. using ::uint8_t;
  156. using ::uint16_t;
  157. using ::uint32_t;
  158. using ::uint64_t;
  159. #endif /* Posix */
  160. } // namespace internal
  161. using std::size_t;
  162. using std::ptrdiff_t;
  163. //! The function returns the interface version of the TBB shared library being used.
  164. /**
  165. * The version it returns is determined at runtime, not at compile/link time.
  166. * So it can be different than the value of TBB_INTERFACE_VERSION obtained at compile time.
  167. */
  168. extern "C" int __TBB_EXPORTED_FUNC TBB_runtime_interface_version();
  169. /**
  170. * @cond INTERNAL
  171. * @brief Identifiers declared inside namespace internal should never be used directly by client code.
  172. */
  173. namespace internal {
  174. //! Compile-time constant that is upper bound on cache line/sector size.
  175. /** It should be used only in situations where having a compile-time upper
  176. bound is more useful than a run-time exact answer.
  177. @ingroup memory_allocation */
  178. const size_t NFS_MaxLineSize = 128;
  179. /** Label for data that may be accessed from different threads, and that may eventually become wrapped
  180. in a formal atomic type.
  181. Note that no problems have yet been observed relating to the definition currently being empty,
  182. even if at least "volatile" would seem to be in order to avoid data sometimes temporarily hiding
  183. in a register (although "volatile" as a "poor man's atomic" lacks several other features of a proper
  184. atomic, some of which are now provided instead through specialized functions).
  185. Note that usage is intentionally compatible with a definition as qualifier "volatile",
  186. both as a way to have the compiler help enforce use of the label and to quickly rule out
  187. one potential issue.
  188. Note however that, with some architecture/compiler combinations, e.g. on IA-64 architecture, "volatile"
  189. also has non-portable memory semantics that are needlessly expensive for "relaxed" operations.
  190. Note that this must only be applied to data that will not change bit patterns when cast to/from
  191. an integral type of the same length; tbb::atomic must be used instead for, e.g., floating-point types.
  192. TODO: apply wherever relevant **/
  193. #define __TBB_atomic // intentionally empty, see above
  194. #if __TBB_OVERRIDE_PRESENT
  195. #define __TBB_override override
  196. #else
  197. #define __TBB_override // formal comment only
  198. #endif
  199. #if __TBB_CPP17_FALLTHROUGH_PRESENT
  200. #define __TBB_fallthrough [[fallthrough]]
  201. #elif __TBB_FALLTHROUGH_PRESENT
  202. #define __TBB_fallthrough __attribute__ ((fallthrough))
  203. #else
  204. #define __TBB_fallthrough
  205. #endif
  206. template<class T, size_t S, size_t R>
  207. struct padded_base : T {
  208. char pad[S - R];
  209. };
  210. template<class T, size_t S> struct padded_base<T, S, 0> : T {};
  211. //! Pads type T to fill out to a multiple of cache line size.
  212. template<class T, size_t S = NFS_MaxLineSize>
  213. struct padded : padded_base<T, S, sizeof(T) % S> {};
  214. //! Extended variant of the standard offsetof macro
  215. /** The standard offsetof macro is not sufficient for TBB as it can be used for
  216. POD-types only. The constant 0x1000 (not NULL) is necessary to appease GCC. **/
  217. #define __TBB_offsetof(class_name, member_name) \
  218. ((ptrdiff_t)&(reinterpret_cast<class_name*>(0x1000)->member_name) - 0x1000)
  219. //! Returns address of the object containing a member with the given name and address
  220. #define __TBB_get_object_ref(class_name, member_name, member_addr) \
  221. (*reinterpret_cast<class_name*>((char*)member_addr - __TBB_offsetof(class_name, member_name)))
  222. //! Throws std::runtime_error with what() returning error_code description prefixed with aux_info
  223. void __TBB_EXPORTED_FUNC handle_perror( int error_code, const char* aux_info );
  224. #if TBB_USE_EXCEPTIONS
  225. #define __TBB_TRY try
  226. #define __TBB_CATCH(e) catch(e)
  227. #define __TBB_THROW(e) throw e
  228. #define __TBB_RETHROW() throw
  229. #else /* !TBB_USE_EXCEPTIONS */
  230. inline bool __TBB_false() { return false; }
  231. #define __TBB_TRY
  232. #define __TBB_CATCH(e) if ( tbb::internal::__TBB_false() )
  233. #define __TBB_THROW(e) tbb::internal::suppress_unused_warning(e)
  234. #define __TBB_RETHROW() ((void)0)
  235. #endif /* !TBB_USE_EXCEPTIONS */
  236. //! Report a runtime warning.
  237. void __TBB_EXPORTED_FUNC runtime_warning( const char* format, ... );
  238. #if TBB_USE_ASSERT
  239. static void* const poisoned_ptr = reinterpret_cast<void*>(-1);
  240. //! Set p to invalid pointer value.
  241. // Also works for regular (non-__TBB_atomic) pointers.
  242. template<typename T>
  243. inline void poison_pointer( T* __TBB_atomic & p ) { p = reinterpret_cast<T*>(poisoned_ptr); }
  244. /** Expected to be used in assertions only, thus no empty form is defined. **/
  245. template<typename T>
  246. inline bool is_poisoned( T* p ) { return p == reinterpret_cast<T*>(poisoned_ptr); }
  247. #else
  248. template<typename T>
  249. inline void poison_pointer( T* __TBB_atomic & ) {/*do nothing*/}
  250. #endif /* !TBB_USE_ASSERT */
  251. //! Cast between unrelated pointer types.
  252. /** This method should be used sparingly as a last resort for dealing with
  253. situations that inherently break strict ISO C++ aliasing rules. */
  254. // T is a pointer type because it will be explicitly provided by the programmer as a template argument;
  255. // U is a referent type to enable the compiler to check that "ptr" is a pointer, deducing U in the process.
  256. template<typename T, typename U>
  257. inline T punned_cast( U* ptr ) {
  258. uintptr_t x = reinterpret_cast<uintptr_t>(ptr);
  259. return reinterpret_cast<T>(x);
  260. }
  261. #if __TBB_DEFAULTED_AND_DELETED_FUNC_PRESENT
  262. //! Base class for types that should not be assigned.
  263. class no_assign {
  264. public:
  265. void operator=( const no_assign& ) = delete;
  266. no_assign( const no_assign& ) = default;
  267. no_assign() = default;
  268. };
  269. //! Base class for types that should not be copied or assigned.
  270. class no_copy: no_assign {
  271. public:
  272. no_copy( const no_copy& ) = delete;
  273. no_copy() = default;
  274. };
  275. #else /*__TBB_DEFAULTED_AND_DELETED_FUNC_PRESENT*/
  276. //! Base class for types that should not be assigned.
  277. class no_assign {
  278. // Deny assignment
  279. void operator=( const no_assign& );
  280. public:
  281. #if __GNUC__
  282. //! Explicitly define default construction, because otherwise gcc issues gratuitous warning.
  283. no_assign() {}
  284. #endif /* __GNUC__ */
  285. };
  286. //! Base class for types that should not be copied or assigned.
  287. class no_copy: no_assign {
  288. //! Deny copy construction
  289. no_copy( const no_copy& );
  290. public:
  291. //! Allow default construction
  292. no_copy() {}
  293. };
  294. #endif /*__TBB_DEFAULTED_AND_DELETED_FUNC_PRESENT*/
  295. #if TBB_DEPRECATED_MUTEX_COPYING
  296. class mutex_copy_deprecated_and_disabled {};
  297. #else
  298. // By default various implementations of mutexes are not copy constructible
  299. // and not copy assignable.
  300. class mutex_copy_deprecated_and_disabled : no_copy {};
  301. #endif
  302. //! A function to check if passed in pointer is aligned on a specific border
  303. template<typename T>
  304. inline bool is_aligned(T* pointer, uintptr_t alignment) {
  305. return 0==((uintptr_t)pointer & (alignment-1));
  306. }
  307. //! A function to check if passed integer is a power of 2
  308. template<typename integer_type>
  309. inline bool is_power_of_two(integer_type arg) {
  310. return arg && (0 == (arg & (arg - 1)));
  311. }
  312. //! A function to compute arg modulo divisor where divisor is a power of 2.
  313. template<typename argument_integer_type, typename divisor_integer_type>
  314. inline argument_integer_type modulo_power_of_two(argument_integer_type arg, divisor_integer_type divisor) {
  315. __TBB_ASSERT( is_power_of_two(divisor), "Divisor should be a power of two" );
  316. return (arg & (divisor - 1));
  317. }
  318. //! A function to determine if arg is a power of 2 at least as big as another power of 2.
  319. // i.e. for strictly positive i and j, with j being a power of 2,
  320. // determines whether i==j<<k for some nonnegative k (so i==j yields true).
  321. template<typename argument_integer_type, typename power2_integer_type>
  322. inline bool is_power_of_two_at_least(argument_integer_type arg, power2_integer_type power2) {
  323. __TBB_ASSERT( is_power_of_two(power2), "Divisor should be a power of two" );
  324. return 0 == (arg & (arg - power2));
  325. }
  326. //! Utility template function to prevent "unused" warnings by various compilers.
  327. template<typename T1> void suppress_unused_warning( const T1& ) {}
  328. template<typename T1, typename T2> void suppress_unused_warning( const T1&, const T2& ) {}
  329. template<typename T1, typename T2, typename T3> void suppress_unused_warning( const T1&, const T2&, const T3& ) {}
  330. // Struct to be used as a version tag for inline functions.
  331. /** Version tag can be necessary to prevent loader on Linux from using the wrong
  332. symbol in debug builds (when inline functions are compiled as out-of-line). **/
  333. struct version_tag_v3 {};
  334. typedef version_tag_v3 version_tag;
  335. } // internal
  336. //! Dummy type that distinguishes splitting constructor from copy constructor.
  337. /**
  338. * See description of parallel_for and parallel_reduce for example usages.
  339. * @ingroup algorithms
  340. */
  341. class split {
  342. };
  343. //! Type enables transmission of splitting proportion from partitioners to range objects
  344. /**
  345. * In order to make use of such facility Range objects must implement
  346. * splitting constructor with this type passed and initialize static
  347. * constant boolean field 'is_splittable_in_proportion' with the value
  348. * of 'true'
  349. */
  350. class proportional_split: internal::no_assign {
  351. public:
  352. proportional_split(size_t _left = 1, size_t _right = 1) : my_left(_left), my_right(_right) { }
  353. size_t left() const { return my_left; }
  354. size_t right() const { return my_right; }
  355. // used when range does not support proportional split
  356. operator split() const { return split(); }
  357. #if __TBB_ENABLE_RANGE_FEEDBACK
  358. void set_proportion(size_t _left, size_t _right) {
  359. my_left = _left;
  360. my_right = _right;
  361. }
  362. #endif
  363. private:
  364. size_t my_left, my_right;
  365. };
  366. } // tbb
  367. // Following is a set of classes and functions typically used in compile-time "metaprogramming".
  368. // TODO: move all that to a separate header
  369. #if __TBB_CPP11_SMART_POINTERS_PRESENT
  370. #include <memory> // for unique_ptr
  371. #endif
  372. #if __TBB_CPP11_RVALUE_REF_PRESENT || __TBB_CPP11_DECLTYPE_PRESENT || _LIBCPP_VERSION
  373. #include <utility> // for std::move, std::forward, std::declval
  374. #endif
  375. namespace tbb {
  376. namespace internal {
  377. #if __TBB_CPP11_SMART_POINTERS_PRESENT && __TBB_CPP11_RVALUE_REF_PRESENT && __TBB_CPP11_VARIADIC_TEMPLATES_PRESENT
  378. template<typename T, typename... Args>
  379. std::unique_ptr<T> make_unique(Args&&... args) {
  380. return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
  381. }
  382. #endif
  383. //! Class for determining type of std::allocator<T>::value_type.
  384. template<typename T>
  385. struct allocator_type {
  386. typedef T value_type;
  387. };
  388. #if _MSC_VER
  389. //! Microsoft std::allocator has non-standard extension that strips const from a type.
  390. template<typename T>
  391. struct allocator_type<const T> {
  392. typedef T value_type;
  393. };
  394. #endif
  395. // Ad-hoc implementation of true_type & false_type
  396. // Intended strictly for internal use! For public APIs (traits etc), use C++11 analogues.
  397. template <bool v>
  398. struct bool_constant {
  399. static /*constexpr*/ const bool value = v;
  400. };
  401. typedef bool_constant<true> true_type;
  402. typedef bool_constant<false> false_type;
  403. //! A template to select either 32-bit or 64-bit constant as compile time, depending on machine word size.
  404. template <unsigned u, unsigned long long ull >
  405. struct select_size_t_constant {
  406. //Explicit cast is needed to avoid compiler warnings about possible truncation.
  407. //The value of the right size, which is selected by ?:, is anyway not truncated or promoted.
  408. static const size_t value = (size_t)((sizeof(size_t)==sizeof(u)) ? u : ull);
  409. };
  410. #if __TBB_CPP11_RVALUE_REF_PRESENT
  411. using std::move;
  412. using std::forward;
  413. #elif defined(_LIBCPP_NAMESPACE)
  414. // libc++ defines "pre-C++11 move and forward" similarly to ours; use it to avoid name conflicts in some cases.
  415. using std::_LIBCPP_NAMESPACE::move;
  416. using std::_LIBCPP_NAMESPACE::forward;
  417. #else
  418. // It is assumed that cv qualifiers, if any, are part of the deduced type.
  419. template <typename T>
  420. T& move( T& x ) { return x; }
  421. template <typename T>
  422. T& forward( T& x ) { return x; }
  423. #endif /* __TBB_CPP11_RVALUE_REF_PRESENT */
  424. // Helper macros to simplify writing templates working with both C++03 and C++11.
  425. #if __TBB_CPP11_RVALUE_REF_PRESENT
  426. #define __TBB_FORWARDING_REF(A) A&&
  427. #else
  428. // It is assumed that cv qualifiers, if any, are part of a deduced type.
  429. // Thus this macro should not be used in public interfaces.
  430. #define __TBB_FORWARDING_REF(A) A&
  431. #endif
  432. #if __TBB_CPP11_VARIADIC_TEMPLATES_PRESENT
  433. #define __TBB_PARAMETER_PACK ...
  434. #define __TBB_PACK_EXPANSION(A) A...
  435. #else
  436. #define __TBB_PARAMETER_PACK
  437. #define __TBB_PACK_EXPANSION(A) A
  438. #endif /* __TBB_CPP11_VARIADIC_TEMPLATES_PRESENT */
  439. #if __TBB_CPP11_DECLTYPE_PRESENT
  440. #if __TBB_CPP11_DECLVAL_BROKEN
  441. // Ad-hoc implementation of std::declval
  442. template <class T> __TBB_FORWARDING_REF(T) declval() /*noexcept*/;
  443. #else
  444. using std::declval;
  445. #endif
  446. #endif
  447. template <bool condition>
  448. struct STATIC_ASSERTION_FAILED;
  449. template <>
  450. struct STATIC_ASSERTION_FAILED<false> { enum {value=1};};
  451. template<>
  452. struct STATIC_ASSERTION_FAILED<true>; //intentionally left undefined to cause compile time error
  453. //! @endcond
  454. }} // namespace tbb::internal
  455. #if __TBB_STATIC_ASSERT_PRESENT
  456. #define __TBB_STATIC_ASSERT(condition,msg) static_assert(condition,msg)
  457. #else
  458. //please note condition is intentionally inverted to get a bit more understandable error msg
  459. #define __TBB_STATIC_ASSERT_IMPL1(condition,msg,line) \
  460. enum {static_assert_on_line_##line = tbb::internal::STATIC_ASSERTION_FAILED<!(condition)>::value}
  461. #define __TBB_STATIC_ASSERT_IMPL(condition,msg,line) __TBB_STATIC_ASSERT_IMPL1(condition,msg,line)
  462. //! Verify condition, at compile time
  463. #define __TBB_STATIC_ASSERT(condition,msg) __TBB_STATIC_ASSERT_IMPL(condition,msg,__LINE__)
  464. #endif
  465. #endif /* RC_INVOKED */
  466. #endif /* __TBB_tbb_stddef_H */