Таким образом, в следующем коде, который я использую std::thread()
для сообщения о ходе выполнения программы, пример был изменен, чтобы сообщать с неоправданным интервалом с неинформативным сообщением, чтобы продемонстрировать проблему.
#include <Rcpp.h>
#include <thread>
#include <chrono>
#include <atomic>
using namespace Rcpp;
void reporter(const std::atomic<bool> &running) {
while (running) {
Rprintf( "Program running...\n" );
std::this_thread::sleep_for(std::chrono::microseconds(10));
}
}
// [[Rcpp::export]]
void example() {
int i = 1;
std::atomic<bool> running{true};
std::thread reporter_thread(
[&] () { reporter(running); }
);
while (true) {
i++;
i--;
}
return;
}
На моем MacBook Pro 2017 года это вызывает сбой stack usage is too close to the limit
на 93-м отпечатке. Это также дает сбой, если я перейду на Rprintf
, однако, насколько я могу судить, std::cout
неуязвим.
Я могу изменить код так, чтобы печать происходила в родительском потоке с флагом, который переключается в порожденном потоке, что также, по-видимому, позволяет избежать сбоя.
#include <Rcpp.h>
#include <thread>
#include <chrono>
#include <atomic>
using namespace Rcpp;
void reporter(const std::atomic<bool> &running, std::atomic<bool> &print_message) {
while (running) {
std::this_thread::sleep_for(std::chrono::microseconds(10));
print_message = true;
}
}
// [[Rcpp::export]]
void example() {
int i = 1;
std::atomic<bool> running{true};
std::atomic<bool> print_message{true};
std::thread reporter_thread(
[&] () { reporter(running, print_message); }
);
while (true) {
i++;
i--;
if (print_message)
Rprintf( "Program running...\n" );
print_message = false;
}
return;
}
Итак, у меня два вопроса:
- Почему первая версия вызывает сбой.
- Вторая версия гарантированно безопасна?