Skip to content

Commit 45c2298

Browse files
authored
Add CI workflow for testing documentation examples (#1629)
1 parent d3ad09c commit 45c2298

35 files changed

+991
-482
lines changed

.github/workflows/ci.yml

Lines changed: 51 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Copyright (c) 2021-2024 Intel Corporation
1+
# Copyright (c) 2021-2025 Intel Corporation
22
#
33
# Licensed under the Apache License, Version 2.0 (the "License");
44
# you may not use this file except in compliance with the License.
@@ -366,3 +366,53 @@ jobs:
366366
-DCMAKE_BUILD_TYPE=${{ matrix.build_type }} -DCMAKE_CXX_COMPILER=${{ matrix.cxx_compiler }} `
367367
-DCMAKE_C_COMPILER=${{ matrix.c_compiler }} -DTBB_CPF=${{ matrix.preview }} -DTBB_TEST=OFF -DTBB_EXAMPLES=ON ..
368368
cmake --build . -v --target light_test_examples
369+
370+
linux-doc-examples-testing:
371+
name: doc_examples_${{ matrix.os }}_${{ matrix.cxx_compiler }}_cxx${{ matrix.std }}_${{ matrix.build_type }}
372+
runs-on: ['${{ matrix.os }}']
373+
timeout-minutes: 10
374+
strategy:
375+
fail-fast: false
376+
matrix:
377+
include:
378+
- os: ubuntu-latest
379+
c_compiler: gcc
380+
cxx_compiler: g++
381+
std: 20
382+
build_type: relwithdebinfo
383+
steps:
384+
- uses: actions/checkout@v4
385+
- name: Test doc examples
386+
run: |
387+
mkdir build && cd build
388+
cmake -DCMAKE_CXX_STANDARD=${{ matrix.std }} -DCMAKE_BUILD_TYPE=${{ matrix.build_type}} \
389+
-DCMAKE_CXX_COMPILER=${{ matrix.cxx_compiler }} -DCMAKE_C_COMPILER=${{ matrix.c_compiler }} \
390+
-DTBB_TEST=OFF -DTBB_DOC_EXAMPLES=ON ..
391+
cmake --build . -v --parallel --target build-doc-examples
392+
ctest -C ${{ matrix.build_type }} --timeout ${env:TEST_TIMEOUT} --output-on-failure -L doc-examples
393+
394+
windows-doc-examples-testing:
395+
name: doc_examples_${{ matrix.os }}_${{ matrix.cxx_compiler }}_cxx${{ matrix.std }}_${{ matrix.build_type }}
396+
runs-on: ['${{ matrix.os }}']
397+
timeout-minutes: 10
398+
strategy:
399+
fail-fast: false
400+
matrix:
401+
include:
402+
- os: windows-2022
403+
generator: "Visual Studio 17 2022"
404+
c_compiler: cl
405+
cxx_compiler: cl
406+
std: 20
407+
build_type: relwithdebinfo
408+
steps:
409+
- uses: actions/checkout@v4
410+
- name: Test doc examples
411+
run: |
412+
mkdir build
413+
cd build
414+
cmake -G "${{ matrix.generator }}" -A x64 -DCMAKE_CXX_STANDARD=${{ matrix.std }} `
415+
-DCMAKE_BUILD_TYPE=${{ matrix.build_type}} -DCMAKE_CXX_COMPILER=${{ matrix.cxx_compiler }} `
416+
-DCMAKE_C_COMPILER=${{ matrix.c_compiler }} -DTBB_TEST=OFF -DTBB_DOC_EXAMPLES=ON ..
417+
cmake --build . --config ${{ matrix.build_type }} -v --parallel --target build-doc-examples
418+
ctest -C ${{ matrix.build_type }} --timeout ${env:TEST_TIMEOUT} --output-on-failure -L doc-examples

CMakeLists.txt

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -330,6 +330,18 @@ if (TBB_EXAMPLES)
330330
add_subdirectory(examples)
331331
endif()
332332

333+
334+
if (TBB_DOC_EXAMPLES)
335+
set(TBB_DOC_EXAMPLES_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/doc/main/examples_testing")
336+
if (NOT EXISTS ${TBB_DOC_EXAMPLES_DIRECTORY})
337+
message(FATAL_ERROR "Documentation examples are not found while testing was enabled")
338+
else()
339+
message(STATUS "Enabling testing for examples from documentation")
340+
enable_testing()
341+
add_subdirectory(${TBB_DOC_EXAMPLES_DIRECTORY})
342+
endif()
343+
endif()
344+
333345
if (TBB_BENCH)
334346
if (NOT EXISTS ${CMAKE_CURRENT_LIST_DIR}/benchmark)
335347
message(FATAL_ERROR "Benchmarks are not supported yet")
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
# Copyright (c) 2025 Intel Corporation
2+
#
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+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
cmake_minimum_required(VERSION 3.11)
16+
project(doc_examples_testing LANGUAGES CXX)
17+
18+
set(_reference_examples_path "${CMAKE_CURRENT_SOURCE_DIR}/../reference/examples")
19+
set(_userguide_examples_path "${CMAKE_CURRENT_SOURCE_DIR}/../tbb_userguide/examples")
20+
21+
add_custom_target(build-doc-examples
22+
COMMENT "Build oneTBB documentation samples")
23+
set(doc_examples_test_label "doc-examples")
24+
25+
macro(add_doc_example _doc_example_path)
26+
get_filename_component(_doc_example_name "${_doc_example_path}" NAME_WE)
27+
add_executable(${_doc_example_name} EXCLUDE_FROM_ALL "${_doc_example_path}")
28+
29+
add_dependencies(${_doc_example_name} TBB::tbb TBB::tbbmalloc TBB::tbbmalloc_proxy)
30+
target_link_libraries(${_doc_example_name} TBB::tbb TBB::tbbmalloc TBB::tbbmalloc_proxy)
31+
32+
add_dependencies(build-doc-examples ${_doc_example_name})
33+
add_test(NAME ${_doc_example_name} COMMAND ${_doc_example_name})
34+
set_tests_properties(${_doc_example_name} PROPERTIES LABELS "${doc_examples_test_label}")
35+
endmacro()
36+
37+
file(GLOB_RECURSE DOC_EXAMPLES_LIST "${_reference_examples_path}/*.cpp" "${_userguide_examples_path}/*.cpp")
38+
39+
foreach(_doc_example_path IN LISTS DOC_EXAMPLES_LIST)
40+
add_doc_example(${_doc_example_path})
41+
endforeach()

doc/main/reference/custom_mutex_chmap.rst

Lines changed: 4 additions & 89 deletions
Original file line numberDiff line numberDiff line change
@@ -67,92 +67,7 @@ and ``oneapi::tbb::rw_mutex`` meet the requirements above.
6767
The example below demonstrates how to wrap ``std::shared_mutex`` (C++17) to meet the requirements
6868
of `ReaderWriterMutex` and how to customize ``concurrent_hash_map`` to use this mutex.
6969

70-
.. code:: cpp
71-
72-
#define TBB_PREVIEW_CONCURRENT_HASH_MAP_EXTENSIONS 1
73-
#include "oneapi/tbb/concurrent_hash_map.h"
74-
#include <shared_mutex>
75-
76-
class SharedMutexWrapper {
77-
public:
78-
// ReaderWriterMutex requirements
79-
80-
static constexpr bool is_rw_mutex = true;
81-
static constexpr bool is_recursive_mutex = false;
82-
static constexpr bool is_fair_mutex = false;
83-
84-
class scoped_lock {
85-
public:
86-
scoped_lock() : my_mutex_ptr(nullptr), my_writer_flag(false) {}
87-
scoped_lock(SharedMutexWrapper& mutex, bool write = true)
88-
: my_mutex_ptr(&mutex), my_writer_flag(write)
89-
{
90-
if (my_writer_flag) {
91-
my_mutex_ptr->my_mutex.lock();
92-
} else {
93-
my_mutex_ptr->my_mutex.lock_shared();
94-
}
95-
}
96-
97-
~scoped_lock() {
98-
if (my_mutex_ptr) release();
99-
}
100-
101-
void acquire(SharedMutexWrapper& mutex, bool write = true) {
102-
if (my_mutex_ptr) release();
103-
104-
my_mutex_ptr = &mutex;
105-
my_writer_flag = write;
106-
107-
if (my_writer_flag) {
108-
my_mutex_ptr->my_mutex.lock();
109-
} else {
110-
my_mutex_ptr->my_mutex.lock_shared();
111-
}
112-
}
113-
114-
void release() {
115-
if (my_writer_flag) {
116-
my_mutex_ptr->my_mutex.unlock();
117-
} else {
118-
my_mutex_ptr->my_mutex.unlock_shared();
119-
}
120-
}
121-
122-
bool upgrade_to_writer() {
123-
// std::shared_mutex does not have the upgrade/downgrade parallel_for_each_semantics
124-
if (my_writer_flag) return true; // Already a writer
125-
126-
my_mutex_ptr->my_mutex.unlock_shared();
127-
my_mutex_ptr->my_mutex.lock();
128-
return false; // The lock was reacquired
129-
}
130-
131-
bool downgrade_to_reader() {
132-
if (!my_writer_flag) return true; // Already a reader
133-
134-
my_mutex_ptr->my_mutex.unlock();
135-
my_mutex_ptr->my_mutex.lock_shared();
136-
return false;
137-
}
138-
139-
bool is_writer() const {
140-
return my_writer_flag;
141-
}
142-
143-
private:
144-
SharedMutexWrapper* my_mutex_ptr;
145-
bool my_writer_flag;
146-
};
147-
private:
148-
std::shared_mutex my_mutex;
149-
}; // struct SharedMutexWrapper
150-
151-
int main() {
152-
using map_type = oneapi::tbb::concurrent_hash_map<int, int,
153-
oneapi::tbb::tbb_hash_compare<int>,
154-
oneapi::tbb::tbb_allocator<std::pair<const int, int>>,
155-
SharedMutexWrapper>;
156-
157-
map_type map; // This object will use SharedMutexWrapper for thread safety of insert/find/erase operations
158-
}
70+
.. literalinclude:: ./examples/custom_mutex_chmap_example.cpp
71+
:language: c++
72+
:start-after: /*begin_custom_mutex_chmap_example*/
73+
:end-before: /*end_custom_mutex_chmap_example*/
Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
/*
2+
Copyright (c) 2025 Intel Corporation
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
#if __cplusplus >= 201703L
18+
19+
/*begin_custom_mutex_chmap_example*/
20+
#define TBB_PREVIEW_CONCURRENT_HASH_MAP_EXTENSIONS 1
21+
#include "oneapi/tbb/concurrent_hash_map.h"
22+
#include <shared_mutex>
23+
24+
class SharedMutexWrapper {
25+
public:
26+
// ReaderWriterMutex requirements
27+
28+
static constexpr bool is_rw_mutex = true;
29+
static constexpr bool is_recursive_mutex = false;
30+
static constexpr bool is_fair_mutex = false;
31+
32+
class scoped_lock {
33+
public:
34+
scoped_lock() : my_mutex_ptr(nullptr), my_writer_flag(false) {}
35+
scoped_lock(SharedMutexWrapper& mutex, bool write = true)
36+
: my_mutex_ptr(&mutex), my_writer_flag(write)
37+
{
38+
if (my_writer_flag) {
39+
my_mutex_ptr->my_mutex.lock();
40+
} else {
41+
my_mutex_ptr->my_mutex.lock_shared();
42+
}
43+
}
44+
45+
~scoped_lock() {
46+
if (my_mutex_ptr) release();
47+
}
48+
49+
void acquire(SharedMutexWrapper& mutex, bool write = true) {
50+
if (my_mutex_ptr) release();
51+
52+
my_mutex_ptr = &mutex;
53+
my_writer_flag = write;
54+
55+
if (my_writer_flag) {
56+
my_mutex_ptr->my_mutex.lock();
57+
} else {
58+
my_mutex_ptr->my_mutex.lock_shared();
59+
}
60+
}
61+
62+
bool try_acquire(SharedMutexWrapper& mutex, bool write = true) {
63+
if (my_mutex_ptr) release();
64+
65+
my_mutex_ptr = &mutex;
66+
67+
bool result = false;
68+
69+
if (my_writer_flag) {
70+
result = my_mutex_ptr->my_mutex.try_lock();
71+
} else {
72+
result = my_mutex_ptr->my_mutex.try_lock_shared();
73+
}
74+
75+
if (result) my_writer_flag = write;
76+
return result;
77+
}
78+
79+
void release() {
80+
if (my_writer_flag) {
81+
my_mutex_ptr->my_mutex.unlock();
82+
} else {
83+
my_mutex_ptr->my_mutex.unlock_shared();
84+
}
85+
}
86+
87+
bool upgrade_to_writer() {
88+
// std::shared_mutex does not have the upgrade/downgrade semantics
89+
if (my_writer_flag) return true; // Already a writer
90+
91+
my_mutex_ptr->my_mutex.unlock_shared();
92+
my_mutex_ptr->my_mutex.lock();
93+
return false; // The lock was reacquired
94+
}
95+
96+
bool downgrade_to_reader() {
97+
if (!my_writer_flag) return true; // Already a reader
98+
99+
my_mutex_ptr->my_mutex.unlock();
100+
my_mutex_ptr->my_mutex.lock_shared();
101+
return false;
102+
}
103+
104+
bool is_writer() const {
105+
return my_writer_flag;
106+
}
107+
108+
private:
109+
SharedMutexWrapper* my_mutex_ptr;
110+
bool my_writer_flag;
111+
};
112+
private:
113+
std::shared_mutex my_mutex;
114+
}; // struct SharedMutexWrapper
115+
116+
int main() {
117+
using map_type = oneapi::tbb::concurrent_hash_map<int, int,
118+
oneapi::tbb::tbb_hash_compare<int>,
119+
oneapi::tbb::tbb_allocator<std::pair<const int, int>>,
120+
SharedMutexWrapper>;
121+
122+
map_type map; // This object will use SharedMutexWrapper for thread safety of insert/find/erase operations
123+
}
124+
/*end_custom_mutex_chmap_example*/
125+
126+
#else // C++17
127+
// Skip
128+
int main() {}
129+
#endif
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
/*
2+
Copyright (c) 2025 Intel Corporation
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
/*begin_fixed_pool_example*/
18+
#define TBB_PREVIEW_MEMORY_POOL 1
19+
#include "oneapi/tbb/memory_pool.h"
20+
21+
int main() {
22+
char buf[1024];
23+
oneapi::tbb::fixed_pool my_pool(buf, 1024);
24+
25+
void* my_ptr = my_pool.malloc(10);
26+
my_pool.free(my_ptr);
27+
}
28+
/*end_fixed_pool_example*/

0 commit comments

Comments
 (0)