Позвольте мне начать с короткого примера
class A
{
public:
A() :
thread_([this] {
std::unique_lock<std::mutex> lk(mtx_);
cv_.wait(lk, [this] { return quit_; });
})
{
throw std::exception();
}
~A()
{
quit_ = true;
cv_.notify_one();
thread_.join();
}
private:
bool quit_ = false;
std::mutex mtx_;
std::condition_variable cv_;
std::thread thread_;
};
int main()
{
try { A a; }
catch (...) {}
// Does not reach this point
}
Поскольку в конструкторе создается исключение, элементы уничтожаются в обратном порядке. член thread_ по-прежнему доступен для соединения, поэтому вызывается терминатор.
Довольно просто написать класс-оболочку потока с настраиваемым деструктором.
Например, что-то вроде этого:
class ThreadWrapper
{
public:
ThreadWrapper(std::function<void(std::thread & t)> onDestruct, std::thread&& thread) :
onDestruct_(onDestruct),
thread_(std::move(thread))
{
}
~ThreadWrapper()
{
onDestruct_(thread_);
}
private:
std::function<void(std::thread & t)> onDestruct_;
std::thread thread_;
};
class B
{
public:
B() :
thread_(
[this](std::thread& t) {
quit_ = true;
cv_.notify_one();
t.join();
},
std::thread([this] {
std::unique_lock<std::mutex> lk(mtx_);
cv_.wait(lk, [this] { return quit_; });
}))
{
throw std::exception();
}
private:
bool quit_ = false;
std::mutex mtx_;
std::condition_variable cv_;
ThreadWrapper thread_;
};
Однако, я был удивлен, что не нашел что-то подобное в библиотеке наддува. Самое близкое, что я нашел, это scoped_thread, который позволяет вам передавать указанное c действие в качестве параметра шаблона.
Я что-то упустил?