File: test_tbb_header.cpp

package info (click to toggle)
onetbb 2022.3.0-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 19,440 kB
  • sloc: cpp: 129,228; ansic: 9,745; python: 808; xml: 183; objc: 176; makefile: 66; sh: 66; awk: 41; javascript: 37
file content (332 lines) | stat: -rw-r--r-- 15,964 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
/*
    Copyright (c) 2005-2025 Intel Corporation
    Copyright (c) 2025 UXL Foundation Contributors

    Licensed under the Apache License, Version 2.0 (the "License");
    you may not use this file except in compliance with the License.
    You may obtain a copy of the License at

        http://www.apache.org/licenses/LICENSE-2.0

    Unless required by applicable law or agreed to in writing, software
    distributed under the License is distributed on an "AS IS" BASIS,
    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    See the License for the specific language governing permissions and
    limitations under the License.
*/

//! \file test_tbb_header.cpp
//! \brief Test for [all] specification

/**
    This test ensures that tbb.h brings in all the public TBB interface definitions,
    and if all the necessary symbols are exported from the library.

    Most of the checks happen at the compilation or link phases.
**/

#if __INTEL_COMPILER && _MSC_VER
#pragma warning(disable : 2586) // decorated name length exceeded, name was truncated
#endif

#ifndef NOMINMAX
#define NOMINMAX
#endif // NOMINMAX

#define __TBB_NO_IMPLICIT_LINKAGE 1


#if __TBB_TEST_SECONDARY
    // Test _DEBUG macro custom definitions.
    #if TBB_USE_DEBUG
        #ifdef _DEBUG
            #undef _DEBUG
        #endif /* _DEBUG */
        // Check that empty value successfully enables the debug mode.
        #define _DEBUG
        static bool isDebugExpected = true;
    #else
        // Check that zero value does not enable the debug mode.
        #define _DEBUG 0x0
        static bool isDebugExpected = false;
    #endif /* TBB_USE_DEBUG */
    #define DO_TEST_DEBUG_MACRO 1
#else
    // Test default definitions of _DEBUG.
    #if _DEBUG
        static bool isDebugExpected = true;
        #define DO_TEST_DEBUG_MACRO 1
    #elif _MSC_VER
        // for MSVC, _DEBUG not defined indicates a release mode.
        static bool isDebugExpected = false;
        #define DO_TEST_DEBUG_MACRO 1
    #endif /* _DEBUG */
#endif /* __TBB_TEST_SECONDARY */

#if DO_TEST_DEBUG_MACRO
// Reset TBB_USE_DEBUG defined in makefiles.
#undef TBB_USE_DEBUG
#endif /* DO_TEST_DEBUG_MACRO */
#define __TBB_CONFIG_PREPROC_ONLY _MSC_VER // For MSVC, prevent including standard headers in tbb_config.h
#include "common/config.h"

#include "oneapi/tbb/detail/_config.h"

#if !TBB_USE_DEBUG && defined(_DEBUG)
// TBB_USE_DEBUG is 0 but _DEBUG is defined, it means that _DEBUG is 0
// MSVC C++ headers consider any definition of _DEBUG, including 0, as debug mode
#undef _DEBUG
#endif /* !TBB_USE_DEBUG && defined(_DEBUG) */

#if __TBB_TEST_SECONDARY && TBB_PREVIEW_MEMORY_POOL && defined(_CRTDBG_MAP_ALLOC)
// when _CRTDBG_MAP_ALLOC is defined, the base versions of malloc, free and realloc are replaced with
// their debug versions with different amount of arguments. It is implemented as #define malloc(x) _malloc_dbg(x, additional-args)
// that breaks the definition of tbb::detail::d1::base_pool::malloc/free/realloc
// excluding memory_pool.h from testing when this mode is enabled
#undef TBB_PREVIEW_MEMORY_POOL
#endif

#include "tbb/tbb.h"

#if !__TBB_TEST_SECONDARY
#include "common/test.h"
#endif

static volatile size_t g_sink;

#define TestTypeDefinitionPresence( Type ) g_sink = sizeof(tbb::Type);
#define TestTypeDefinitionPresence2(TypeStart, TypeEnd) g_sink = sizeof(tbb::TypeStart,TypeEnd);
#define TestTypeDefinitionPresence3(TypeStart, TypeMid, TypeEnd) g_sink = sizeof(tbb::TypeStart,TypeMid,TypeEnd);
#define TestFuncDefinitionPresence(Fn, Args, ReturnType) { ReturnType (*pfn)Args = &tbb::Fn; (void)pfn; }

struct Body {
    void operator() () const {}
};
struct Body1 {
    void operator() ( int ) const {}
};
struct Body1a { // feeder body for parallel_do
    void operator() ( int, tbb::feeder<int>& ) const {}
};
struct Body1b { // binary operator for reduction
    int operator() ( const int, const int ) const { return 0; }
};
struct Body1bc { // binary operator for comparison
    bool operator() (const int, const int) const { return false; }
};
struct Body2 {
    Body2 () {}
    Body2 ( const Body2&, tbb::split ) {}
    void operator() ( const tbb::blocked_range<int>& ) const {}
    void join( const Body2& ) {}
};
struct Body2a { // for lambda-friendly parallel_reduce
    int operator() ( const tbb::blocked_range<int>&, const int ) const { return 0; }
};
struct Body3 { // for parallel_scan
    Body3 () {}
    Body3 ( const Body3&, tbb::split ) {}
    void operator() ( const tbb::blocked_range2d<int>&, tbb::pre_scan_tag ) const {}
    void operator() ( const tbb::blocked_range2d<int>&, tbb::final_scan_tag ) const {}
    void reverse_join( Body3& ) {}
    void assign( const Body3& ) {}
};
struct Body3a { // for lambda-friednly parallel_scan
    int operator() ( const tbb::blocked_range<int>&, const int, bool ) const { return 0; }
};
struct Msg {};

// Test if all the necessary symbols are exported for the exceptions thrown by TBB.
// Missing exports result either in link error or in runtime assertion failure.
#include <stdexcept>

template <typename E>
void TestExceptionClassExports ( const E& exc, tbb::detail::exception_id eid ) {
    CHECK( eid < tbb::detail::exception_id::last_entry );
#if TBB_USE_EXCEPTIONS
    for ( int i = 0; i < 2; ++i ) {
        try {
            if ( i == 0 )
                throw exc;
            else
                tbb::detail::throw_exception( eid );
        }
        catch ( E& e ) {
            CHECK_MESSAGE( e.what(), "Missing what() string" );
        }
        catch ( ... ) {
            CHECK_MESSAGE( false, "Unrecognized exception. Likely RTTI related exports are missing" );
        }
    }
#else /* TBB_USE_EXCEPTIONS */
    (void)exc;
#endif /* TBB_USE_EXCEPTIONS */
}

static void TestExceptionClassesExports () {
    TestExceptionClassExports( std::bad_alloc(), tbb::detail::exception_id::bad_alloc );
    TestExceptionClassExports( tbb::bad_last_alloc(), tbb::detail::exception_id::bad_last_alloc );
    TestExceptionClassExports( std::invalid_argument("test"), tbb::detail::exception_id::nonpositive_step );
    TestExceptionClassExports( std::out_of_range("test"), tbb::detail::exception_id::out_of_range );
    TestExceptionClassExports( tbb::missing_wait(), tbb::detail::exception_id::missing_wait );
    TestExceptionClassExports( std::out_of_range("test"), tbb::detail::exception_id::invalid_load_factor );
    TestExceptionClassExports( std::length_error("test"), tbb::detail::exception_id::reservation_length_error );
    TestExceptionClassExports( std::out_of_range("test"), tbb::detail::exception_id::invalid_key );
    TestExceptionClassExports( tbb::user_abort(), tbb::detail::exception_id::user_abort );
    TestExceptionClassExports( std::runtime_error("test"), tbb::detail::exception_id::bad_tagged_msg_cast );
    TestExceptionClassExports( tbb::unsafe_wait("test"), tbb::detail::exception_id::unsafe_wait );
}

#if __TBB_CPF_BUILD
// These names are only tested in "preview" configuration
// When a feature becomes fully supported, its names should be moved to the main test
static void TestPreviewNames() {
    TestTypeDefinitionPresence2( concurrent_lru_cache<int, int> );
    TestTypeDefinitionPresence( isolated_task_group );
#if TBB_PREVIEW_MEMORY_POOL
    TestTypeDefinitionPresence( memory_pool_allocator<int> );
    TestTypeDefinitionPresence( memory_pool<std::allocator<int>> );
    TestTypeDefinitionPresence( fixed_pool );
#endif
}
#endif

static void DefinitionPresence() {
    TestTypeDefinitionPresence( ext::assertion_handler_type );
    TestTypeDefinitionPresence( cache_aligned_allocator<int> );
    TestTypeDefinitionPresence( tbb_hash_compare<int> );
    TestTypeDefinitionPresence2( concurrent_hash_map<int, int> );
    TestTypeDefinitionPresence2( concurrent_unordered_map<int, int> );
    TestTypeDefinitionPresence2( concurrent_unordered_multimap<int, int> );
    TestTypeDefinitionPresence( concurrent_unordered_set<int> );
    TestTypeDefinitionPresence( concurrent_unordered_multiset<int> );
    TestTypeDefinitionPresence2( concurrent_map<int, int> );
    TestTypeDefinitionPresence2( concurrent_multimap<int, int> );
    TestTypeDefinitionPresence( concurrent_set<int> );
    TestTypeDefinitionPresence( concurrent_multiset<int> );
    TestTypeDefinitionPresence( concurrent_bounded_queue<int> );
    TestTypeDefinitionPresence( concurrent_queue<int> );
    TestTypeDefinitionPresence( concurrent_priority_queue<int> );
    TestTypeDefinitionPresence( concurrent_vector<int> );
    TestTypeDefinitionPresence( combinable<int> );
    TestTypeDefinitionPresence( enumerable_thread_specific<int> );
    TestFuncDefinitionPresence( ext::get_assertion_handler, (),
                                tbb::ext::assertion_handler_type );
    TestFuncDefinitionPresence( ext::set_assertion_handler,
                                (tbb::ext::assertion_handler_type),
                                tbb::ext::assertion_handler_type );
    /* Flow graph names */
    TestTypeDefinitionPresence( flow::graph );
    TestTypeDefinitionPresence( flow::continue_msg );
    TestTypeDefinitionPresence2(flow::tagged_msg<int, int> );
    TestFuncDefinitionPresence( flow::make_edge, (tbb::flow::sender<Msg>&, tbb::flow::receiver<Msg>&), void );
    TestFuncDefinitionPresence( flow::remove_edge, (tbb::flow::sender<Msg>&, tbb::flow::receiver<Msg>&), void );
    typedef std::tuple<int, int> intpair;
    TestTypeDefinitionPresence( flow::input_node<int> );
    TestTypeDefinitionPresence3(flow::function_node<int, int, tbb::flow::rejecting> );
    TestTypeDefinitionPresence3(flow::multifunction_node<int, intpair, tbb::flow::queueing> );
    TestTypeDefinitionPresence3(flow::async_node<int, int, tbb::flow::queueing_lightweight> );
    TestTypeDefinitionPresence2(flow::continue_node<int, tbb::flow::lightweight> );
    TestTypeDefinitionPresence2(flow::join_node<intpair, tbb::flow::reserving> );
    TestTypeDefinitionPresence2(flow::join_node<intpair, tbb::flow::key_matching<int> > );
    TestTypeDefinitionPresence( flow::split_node<intpair> );
    TestTypeDefinitionPresence( flow::overwrite_node<int> );
    TestTypeDefinitionPresence( flow::write_once_node<int> );
    TestTypeDefinitionPresence( flow::broadcast_node<int> );
    TestTypeDefinitionPresence( flow::buffer_node<int> );
    TestTypeDefinitionPresence( flow::queue_node<int> );
    TestTypeDefinitionPresence( flow::sequencer_node<int> );
    TestTypeDefinitionPresence( flow::priority_queue_node<int> );
    TestTypeDefinitionPresence( flow::limiter_node<int> );
    TestTypeDefinitionPresence2(flow::indexer_node<int, int> );
    TestTypeDefinitionPresence2(flow::composite_node<std::tuple<int>, std::tuple<int> > );
    /* Mutex names */
    TestTypeDefinitionPresence( null_mutex );
    TestTypeDefinitionPresence( null_rw_mutex );
    TestTypeDefinitionPresence( queuing_mutex );
    TestTypeDefinitionPresence( queuing_rw_mutex );
    TestTypeDefinitionPresence( spin_mutex );
    TestTypeDefinitionPresence( spin_rw_mutex );
    TestTypeDefinitionPresence( mutex );
    TestTypeDefinitionPresence( rw_mutex );
    TestTypeDefinitionPresence( speculative_spin_mutex );
    TestTypeDefinitionPresence( speculative_spin_rw_mutex );
    TestTypeDefinitionPresence( task_group_context );
    TestTypeDefinitionPresence( task_group );
    /* Algorithm related names */
    TestTypeDefinitionPresence( blocked_range<int> );
    TestTypeDefinitionPresence( blocked_range2d<int> );
    TestTypeDefinitionPresence( blocked_range3d<int> );
    TestTypeDefinitionPresence2( blocked_nd_range<int,4> );
    TestTypeDefinitionPresence( collaborative_once_flag );
    TestFuncDefinitionPresence( collaborative_call_once, (tbb::collaborative_once_flag&, const Body&), void );
    TestFuncDefinitionPresence( parallel_invoke, (const Body&, const Body&, const Body&), void );
    TestFuncDefinitionPresence( parallel_for_each, (int*, int*, const Body1&), void );
    TestFuncDefinitionPresence( parallel_for, (int, int, int, const Body1&), void );
    TestFuncDefinitionPresence( parallel_for, (const tbb::blocked_range<int>&, const Body2&, const tbb::simple_partitioner&), void );
    TestFuncDefinitionPresence( parallel_reduce, (const tbb::blocked_range<int>&, const int&, const Body2a&, const Body1b&), int );
    TestFuncDefinitionPresence( parallel_reduce, (const tbb::blocked_range<int>&, Body2&, tbb::affinity_partitioner&), void );
    TestFuncDefinitionPresence( parallel_deterministic_reduce, (const tbb::blocked_range<int>&, const int&, const Body2a&, const Body1b&), int );
    TestFuncDefinitionPresence( parallel_deterministic_reduce, (const tbb::blocked_range<int>&, Body2&, const tbb::static_partitioner&), void );
    TestFuncDefinitionPresence( parallel_scan, (const tbb::blocked_range2d<int>&, Body3&, const tbb::auto_partitioner&), void );
    TestFuncDefinitionPresence( parallel_scan, (const tbb::blocked_range<int>&, const int&, const Body3a&, const Body1b&), int );
    typedef int intarray[10];

    TestFuncDefinitionPresence( parallel_sort, (int*, int*), void );
    TestFuncDefinitionPresence( parallel_sort, (intarray&, const Body1bc&), void );
    TestFuncDefinitionPresence( parallel_pipeline, (size_t, const tbb::filter<void,void>&), void );
    TestFuncDefinitionPresence( parallel_invoke, (const Body&, const Body&, tbb::task_group_context&), void );
    TestFuncDefinitionPresence( parallel_for_each, (const intarray&, const Body1a&, tbb::task_group_context&), void );
    TestFuncDefinitionPresence( parallel_for, (int, int, const Body1&, const tbb::auto_partitioner&, tbb::task_group_context&), void );
    TestFuncDefinitionPresence( parallel_for, (int, int, const Body1&, tbb::task_group_context&), void );
    TestFuncDefinitionPresence( parallel_reduce, (const tbb::blocked_range<int>&, Body2&, const tbb::auto_partitioner&, tbb::task_group_context&), void );
    TestFuncDefinitionPresence( parallel_reduce, (const tbb::blocked_range<int>&, Body2&, tbb::task_group_context&), void );
    TestFuncDefinitionPresence( parallel_deterministic_reduce, (const tbb::blocked_range<int>&, Body2&, const tbb::simple_partitioner&, tbb::task_group_context&), void );
    TestFuncDefinitionPresence( parallel_deterministic_reduce, (const tbb::blocked_range<int>&, Body2&, tbb::task_group_context&), void );
    TestTypeDefinitionPresence( proportional_split );

    TestTypeDefinitionPresence( task_arena );
    TestFuncDefinitionPresence( this_task_arena::current_thread_index, (), int );
    TestFuncDefinitionPresence( this_task_arena::max_concurrency, (), int );
    TestFuncDefinitionPresence( info::numa_nodes, (), std::vector<tbb::numa_node_id> );
    TestFuncDefinitionPresence( info::default_concurrency, (tbb::numa_node_id), int );
    TestTypeDefinitionPresence( task_scheduler_observer );
    TestTypeDefinitionPresence( tbb_allocator<int> );
    TestTypeDefinitionPresence( tick_count );
    TestTypeDefinitionPresence( global_control );
    TestTypeDefinitionPresence( scalable_allocator<int> );

#if __TBB_CPF_BUILD
    TestPreviewNames();
#endif
#ifdef DO_TEST_DEBUG_MACRO
#if TBB_USE_DEBUG
    CHECK_MESSAGE( isDebugExpected, "Debug mode is observed while release mode is expected." );
#else
    CHECK_MESSAGE( !isDebugExpected, "Release mode is observed while debug mode is expected." );
#endif /* TBB_USE_DEBUG */
#endif /* DO_TEST_DEBUG_MACRO */
    TestExceptionClassesExports();
}

#if __TBB_TEST_SECONDARY
/* This mode is used to produce a secondary object file that is linked with
   the main one in order to detect "multiple definition" linker error.
*/
void Secondary() {
    DefinitionPresence();
}
#else
//! Test for deifinition presence
//! \brief \ref interface
TEST_CASE("Test for deifinition presence") {
    DefinitionPresence();
}

void Secondary();
//! Test for "multiple definition" linker error
//! \brief \ref error_guessing
TEST_CASE("Test for multiple definition linker error") {
    Secondary();
}
#endif