There is an object that contains std::thread
that I want to be finished when the object is destroyed.
Minimal working code:
#include <thread>
#include <future>
#include <QEventLoop>
struct Connector
{
Connector(std::string addr, std::function<void(std::string)> cb)
{
std::promise<void> barrier;
auto fut = barrier.get_future();
m_worker = std::thread([addr, cb, &barrier]()
{
QEventLoop loop;
QTimer::singleShot(0, [this, &barrier, &loop]
{
m_quit = [&loop] { QTimer::singleShot(0, &loop, &QEventLoop::quit); };
barrier.set_value();
});
MySocket s(addr, cb);
loop.exec();
});
fut.wait();
}
~Connector()
{
m_quit();
m_worker.join();
}
std::thread worker;
std::function<void()> m_quit;
};
It becomes complex very fast: you can call exit()
on the loop
only after it enters the exec()
, you can't create the loop
outside of the thread.
I only have a solution with a semaphore that is released by a handler that is queued for the execution in this loop. When the semaphore is released I can be sure that the loop is created and running, so it can be terminated with a quit()
message when needed.
Am I missing a simpler way?
Maybe you could pass a reference to a unique_ptr of QEventLoop to the thread and at destruction call exit on that pointer. Like this:
#include <thread>
#include <QEventLoop>
struct Connector
{
Connector()
{
m_worker = std::thread([=]()
{
event_loop = std::make_unique<QEventLoop>();
loop->exec();
});
}
~Connector()
{
event_loop->exit();
m_worker.join();
}
std::unique_ptr<QEventLoop> event_loop;
std::thread worker;
};
Here's my take on it, based on katrasnikj's answer and std::promise docs to ensure that the thread is running by the time the constructor finishes.
struct Connector
{
Connector()
{
std::promise<void> barrier;
auto fut = barrier.get_future();
worker = std::thread([=](std::promise<void>&& barrier)
{
event_loop = std::make_unique<QEventLoop>();
barrier.set_value();
event_loop->exec();
}, std::move(barrier));
fut.wait();
}
~Connector()
{
QTimer::singleShot(0, event_loop.get(), &QEventLoop::quit);
worker.join();
}
std::unique_ptr<QEventLoop> event_loop;
std::thread worker;
};
But you might want to look into using QThread
instead, since it's capable of running its own event loop.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.