FindThreads: Is it really not needed?
The documentation for FindThreads
states:
This module is not needed for C++11 and later if threading is done using
std::thread
from the standard library.
With the following directory structure in mind:
.
├── CMakeLists.txt
├── include
│ └── mylib.h
├── main.cpp
└── src
└── reduce.cpp
I have the following C++ files:
/* include/mylib.h */
#ifndef MYLIB_H_
#define MYLIB_H_
#ifdef __cplusplus
extern "C" {
#endif
double reduce(const double *, const double *);
#ifdef __cplusplus
}
#endif
#endif
/* src/reduce.cpp */
#include <iterator>
#include <mutex>
#include <numeric>
#include <thread>
#include <vector>
#include "mylib.h"
extern "C" {
double reduce(const double *xb, const double *xe) {
const auto d = std::distance(xb, xe);
const auto W = std::thread::hardware_concurrency();
const auto split = d / W;
const auto remain = d % W;
std::vector<std::thread> workers(W);
double res{0};
std::mutex lock;
const double *xb_w{xb};
const double *xe_w;
for (unsigned int widx = 0; widx < W; widx++) {
xe_w = widx < remain ? xb_w + split + 1 : xb_w + split;
workers[widx] = std::thread(
[&lock, &res](const double *xb, const double *xe) {
const double partial = std::accumulate(xb, xe, double{0});
std::lock_guard<std::mutex> guard(lock);
res += partial;
},
xb_w, xe_w);
xb_w = xe_w;
}
for (auto &worker : workers)
worker.join();
return res;
}
}
/* main.cpp */
#include <iostream>
#include <vector>
using namespace std;
#include "mylib.h"
int main(int argc, char *argv[]) {
const int N{100};
vector<double> x(N);
for (int n = 0; n < N; n++)
x[n] = n + 1;
cout << "reduce(x): " << reduce(x.data(), x.data() + x.size()) << '\n';
return 0;
}
and the CMakeLists.txt
file
cmake_minimum_required(VERSION 3.14)
project(dummy LANGUAGES CXX)
# find_package(Threads)
add_library(mylib
include/mylib.h
src/reduce.cpp
)
target_compile_features(mylib
PRIVATE
cxx_std_11
)
# target_link_libraries(mylib
# PRIVATE
# Threads::Threads
# )
target_include_directories(mylib
PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
$<INSTALL_INTERFACE:include>
)
set_target_properties(mylib
PROPERTIES PUBLIC_HEADER include/mylib.h
)
install(TARGETS mylib
ARCHIVE DESTINATION lib
LIBRARY DESTINATION lib
PUBLIC_HEADER DESTINATION include
)
add_executable(main main.cpp)
target_compile_features(main
PRIVATE
cxx_std_11
)
target_link_libraries(main PRIVATE mylib)
The project fails to build main
unless I uncomment the Threads
-related parts. Interesting enough, the build proceeds without any problems with mylib
, and the resulting library is multithreaded when accessed from another language such as Python.
What is the problem with the above project? Is it a bug or is this intended behavior? I would appreciate if you clarified the statement in the documentation that says the FindThreads
module is not needed for C++11 and later, should std::thread
be used from the standard library.