당신이 C ++ (11)를 사용하는 경우, 다음 std::future
이 자동적으로 트랩 예외 작업자 스레드의 상단에 그것을 만들 수 및 지점에서 부모 스레드를 통해 전달할 : 당신이 찾고있는 정확하게 할 수 std::future::get
있다 전화. (뒤에서 이것은 @AnthonyWilliams의 대답에서와 똑같이 발생합니다. 이미 구현되었습니다.)
단점은 "관심을 중지"하는 표준 방법이 없다는 것입니다 std::future
. 소멸자조차도 작업이 완료 될 때까지 단순히 차단됩니다. [편집 2017 : 블로킹-소멸자의 행동이 misfeature입니다 단지 에서 반환 의사 미래의 std::async
당신이 어쨌든 사용해서는 안됩니다. 정상적인 선물은 소멸자에서 차단되지 않습니다. 그러나 사용중인 경우 여전히 작업을 "취소"할 수 없습니다 std::future
. 약속 이행 작업은 아무도 더 이상 대답을 듣지 않더라도 뒤에서 계속 실행됩니다.] 다음은 내가 무엇을 명확히 할 수있는 장난감 예제입니다. 평균:
#include <atomic>
#include <chrono>
#include <exception>
#include <future>
#include <thread>
#include <vector>
#include <stdio.h>
bool is_prime(int n)
{
if (n == 1010) {
puts("is_prime(1010) throws an exception");
throw std::logic_error("1010");
}
/* We actually want this loop to run slowly, for demonstration purposes. */
std::this_thread::sleep_for(std::chrono::milliseconds(100));
for (int i=2; i < n; ++i) { if (n % i == 0) return false; }
return (n >= 2);
}
int worker()
{
static std::atomic<int> hundreds(0);
const int start = 100 * hundreds++;
const int end = start + 100;
int sum = 0;
for (int i=start; i < end; ++i) {
if (is_prime(i)) { printf("%d is prime\n", i); sum += i; }
}
return sum;
}
int spawn_workers(int N)
{
std::vector<std::future<int>> waitables;
for (int i=0; i < N; ++i) {
std::future<int> f = std::async(std::launch::async, worker);
waitables.emplace_back(std::move(f));
}
int sum = 0;
for (std::future<int> &f : waitables) {
sum += f.get(); /* may throw an exception */
}
return sum;
/* But watch out! When f.get() throws an exception, we still need
* to unwind the stack, which means destructing "waitables" and each
* of its elements. The destructor of each std::future will block
* as if calling this->wait(). So in fact this may not do what you
* really want. */
}
int main()
{
try {
int sum = spawn_workers(100);
printf("sum is %d\n", sum);
} catch (std::exception &e) {
/* This line will be printed after all the prime-number output. */
printf("Caught %s\n", e.what());
}
}
방금 std::thread
and 를 사용하여 작업과 유사한 예제를 작성하려고 시도했지만 (libc ++ 사용) std::exception_ptr
문제가 발생 std::exception_ptr
하여 아직 실제로 작동하지 않았습니다. :(
[2017 년 편집 :
int main() {
std::exception_ptr e;
std::thread t1([&e](){
try {
::operator new(-1);
} catch (...) {
e = std::current_exception();
}
});
t1.join();
try {
std::rethrow_exception(e);
} catch (const std::bad_alloc&) {
puts("Success!");
}
}
2013 년에 내가 뭘 잘못하고 있었는지 모르겠지만 그게 내 잘못이라고 확신한다.]