Skip to content

Commit 6799006

Browse files
CMake review (#77)
* Review cmake files * Add tsan for clang and fix races * Remove CMP0135 * Remove Apple tweaks
1 parent 6112237 commit 6799006

File tree

11 files changed

+74
-58
lines changed

11 files changed

+74
-58
lines changed

.devcontainer/Dockerfile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
1818
git \
1919
graphviz \
2020
lcov \
21+
libclang-rt-18-dev \
2122
lldb \
2223
llvm \
2324
nano \

.vscode/settings.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@
4747
"HISTFILE",
4848
"hwrap",
4949
"lgcov",
50+
"libclang",
5051
"lldb",
5152
"ltsan",
5253
"lubsan",

CMakeLists.txt

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,13 @@
11
cmake_minimum_required(VERSION 3.15)
2-
project(cpp_channel)
3-
set(PROJECT_VERSION 1.3.0)
2+
project(cpp_channel VERSION 1.3.0)
43

54
set(CMAKE_CXX_STANDARD 11 CACHE STRING "C++ standard")
6-
set(CMAKE_CXX_STANDARD_REQUIRED YES)
7-
set(CXX_EXTENSIONS NO)
5+
set(CMAKE_CXX_STANDARD_REQUIRED ON)
6+
set(CXX_EXTENSIONS OFF)
87

98
list(APPEND CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake")
109
include(warnings)
1110

12-
include_directories(include)
13-
1411
add_library(msd_channel INTERFACE)
1512
target_include_directories(msd_channel INTERFACE include)
1613

benchmarks/CMakeLists.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
include(FetchContent)
2+
23
if(NOT benchmark_POPULATED)
34
set(BENCHMARK_ENABLE_TESTING OFF CACHE BOOL "" FORCE)
45
set(BENCHMARK_ENABLE_GTEST_TESTS OFF CACHE BOOL "" FORCE)
@@ -10,7 +11,7 @@ endif()
1011
function(package_add_benchmark TESTNAME)
1112
add_executable(${TESTNAME} ${ARGN})
1213
set_target_warnings(${TESTNAME} PRIVATE)
13-
target_link_libraries(${TESTNAME} benchmark)
14+
target_link_libraries(${TESTNAME} msd_channel benchmark)
1415
endfunction()
1516

1617
package_add_benchmark(channel_benchmark channel_benchmark.cpp)

examples/CMakeLists.txt

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,11 @@ function(add_example NAME)
22
add_executable(${NAME} ${ARGN})
33

44
set_target_warnings(${NAME} PRIVATE)
5+
target_link_libraries(${NAME} msd_channel)
56

6-
if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
7+
if(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang")
78
target_compile_options(${NAME} PRIVATE -fsanitize=thread)
8-
target_link_libraries(${NAME} -ltsan)
9+
target_link_options(${NAME} PRIVATE -fsanitize=thread)
910
endif()
1011

1112
add_dependencies(examples ${NAME})

examples/close.cpp

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
#include <future>
44
#include <iostream>
5+
#include <mutex>
6+
#include <string>
57
#include <thread>
68

79
int main()
@@ -12,38 +14,37 @@ int main()
1214
const auto input = [](msd::channel<int>& chan, int time_ms) {
1315
static int inc = 0;
1416

15-
while (true) {
16-
if (chan.closed()) {
17-
break;
18-
}
19-
17+
while (!chan.closed()) {
2018
chan << ++inc;
21-
std::cout << "in: " << inc << "\n";
2219

2320
std::this_thread::sleep_for(std::chrono::milliseconds{time_ms});
2421
}
25-
26-
std::cout << "exit input\n";
2722
};
2823
const auto input_future = std::async(input, std::ref(channel), 10);
2924

3025
// Close the channel after some time
3126
const auto timeout = [](msd::channel<int>& chan, int time_ms) {
3227
std::this_thread::sleep_for(std::chrono::milliseconds{time_ms});
28+
3329
chan.close();
34-
std::cout << "exit timeout\n";
3530
};
3631
auto timeout_future = std::async(timeout, std::ref(channel), 100);
3732

3833
// Display all the data from the channel
3934
// When the channel is closed and empty, the iteration will end
40-
const auto write = [](msd::channel<int>& chan, int time_ms) {
35+
std::mutex cout_mutex;
36+
37+
const auto write = [&cout_mutex](msd::channel<int>& chan, int time_ms) {
4138
for (auto out : chan) {
42-
std::cout << "out: " << out << "\n";
39+
std::string msg{"out: " + std::to_string(out) + "\n"};
40+
41+
{
42+
std::lock_guard<std::mutex> lock(cout_mutex);
43+
std::cout << msg;
44+
}
45+
4346
std::this_thread::sleep_for(std::chrono::milliseconds{time_ms});
4447
}
45-
46-
std::cout << "exit write\n";
4748
};
4849
const auto write_future1 = std::async(write, std::ref(channel), 1);
4950
const auto write_future2 = std::async(write, std::ref(channel), 100);

examples/cmake-project/CMakeLists.txt

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,14 @@ project(cmake_project)
33
set(PROJECT_VERSION 0.1.0)
44

55
set(CMAKE_CXX_STANDARD 11)
6-
set(CMAKE_CXX_STANDARD_REQUIRED YES)
7-
set(CXX_EXTENSIONS NO)
6+
set(CMAKE_CXX_STANDARD_REQUIRED ON)
7+
set(CXX_EXTENSIONS OFF)
88
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -Wpedantic -Werror --coverage")
99

1010
add_executable(cmake_project src/main.cpp)
1111

1212
include(FetchContent)
13+
1314
if(NOT channel_POPULATED)
1415
FetchContent_Declare(channel URL https://github.com/andreiavrammsd/cpp-channel/archive/v1.3.0.zip
1516
DOWNLOAD_EXTRACT_TIMESTAMP TRUE)

examples/merge_channels.cpp

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
#include <chrono>
55
#include <future>
66
#include <iostream>
7+
#include <mutex>
78
#include <sstream>
89
#include <thread>
910

@@ -12,25 +13,36 @@ int main()
1213
msd::channel<int> input_chan{30};
1314
msd::channel<int> output_chan{10};
1415

16+
std::mutex cout_mutex;
17+
1518
// Send to channel
16-
const auto writer = [&input_chan](int begin, int end) {
19+
const auto writer = [&input_chan, &cout_mutex](int begin, int end) {
1720
for (int i = begin; i <= end; ++i) {
1821
input_chan.write(i);
1922

2023
std::stringstream msg;
2124
msg << "Sent " << i << " from " << std::this_thread::get_id() << "\n";
22-
std::cout << msg.str();
25+
26+
{
27+
std::lock_guard<std::mutex> lock(cout_mutex);
28+
std::cout << msg.str();
29+
}
2330

2431
std::this_thread::sleep_for(std::chrono::milliseconds(10)); // simulate work
2532
}
2633
input_chan.close();
2734
};
2835

29-
const auto reader = [&output_chan]() {
36+
// Read
37+
const auto reader = [&output_chan, &cout_mutex]() {
3038
for (const auto out : output_chan) { // blocking until channel is drained (closed and empty)
3139
std::stringstream msg;
3240
msg << "Received " << out << " on " << std::this_thread::get_id() << "\n";
33-
std::cout << msg.str();
41+
42+
{
43+
std::lock_guard<std::mutex> lock(cout_mutex);
44+
std::cout << msg.str();
45+
}
3446

3547
std::this_thread::sleep_for(std::chrono::milliseconds(200)); // simulate work
3648
}

examples/multithreading_static_channel.cpp

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,32 +3,44 @@
33
#include <chrono>
44
#include <future>
55
#include <iostream>
6+
#include <mutex>
67
#include <sstream>
78
#include <thread>
89

910
int main()
1011
{
1112
msd::static_channel<int, 50> chan{}; // always buffered
1213

14+
std::mutex cout_mutex;
15+
1316
// Send to channel
14-
const auto writer = [&chan](int begin, int end) {
17+
const auto writer = [&chan, &cout_mutex](int begin, int end) {
1518
for (int i = begin; i <= end; ++i) {
1619
chan.write(i);
1720

1821
std::stringstream msg;
1922
msg << "Sent " << i << " from " << std::this_thread::get_id() << "\n";
20-
std::cout << msg.str();
23+
24+
{
25+
std::lock_guard<std::mutex> lock(cout_mutex);
26+
std::cout << msg.str();
27+
}
2128

2229
std::this_thread::sleep_for(std::chrono::milliseconds(10)); // simulate work
2330
}
2431
chan.close();
2532
};
2633

27-
const auto reader = [&chan]() {
34+
// Read
35+
const auto reader = [&chan, &cout_mutex]() {
2836
for (const auto out : chan) { // blocking until channel is drained (closed and empty)
2937
std::stringstream msg;
3038
msg << "Received " << out << " on " << std::this_thread::get_id() << "\n";
31-
std::cout << msg.str();
39+
40+
{
41+
std::lock_guard<std::mutex> lock(cout_mutex);
42+
std::cout << msg.str();
43+
}
3244

3345
std::this_thread::sleep_for(std::chrono::milliseconds(200)); // simulate work
3446
}

examples/streaming.cpp

Lines changed: 6 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,9 @@ int main()
1818
const auto input = [](messages& chan, std::size_t thread, std::chrono::milliseconds pause) {
1919
thread_local static std::size_t inc = 0U;
2020

21-
while (true) {
22-
if (chan.closed()) {
23-
return;
24-
}
25-
21+
while (!chan.closed()) {
2622
++inc;
27-
chan << std::string{std::to_string(inc) + " from: " + std::to_string(thread)};
23+
chan << std::string{"Streaming " + std::to_string(inc) + " from thread " + std::to_string(thread)};
2824

2925
std::this_thread::sleep_for(pause);
3026
}
@@ -35,20 +31,17 @@ int main()
3531
in_futures.push_back(std::async(input, std::ref(channel), i, std::chrono::milliseconds{500}));
3632
}
3733

38-
// Stream incoming data to a destination
39-
const auto out = [](messages& chan, std::ostream& stream, const std::string& separator) {
40-
std::move(chan.begin(), chan.end(), std::ostream_iterator<std::string>(stream, separator.c_str()));
41-
};
42-
const auto out_future = std::async(out, std::ref(channel), std::ref(std::cout), "\n");
43-
4434
// Close the channel after some time
4535
const auto timeout = [](messages& chan, std::chrono::milliseconds after) {
4636
std::this_thread::sleep_for(after);
4737
chan.close();
4838
};
4939
const auto timeout_future = std::async(timeout, std::ref(channel), std::chrono::milliseconds{3000U});
5040

51-
out_future.wait();
41+
// Stream incoming data to a destination
42+
std::move(channel.begin(), channel.end(), std::ostream_iterator<std::string>(std::cout, "\n"));
43+
44+
// Wait for other threads
5245
for (auto& future : in_futures) {
5346
future.wait();
5447
}

0 commit comments

Comments
 (0)