34#ifdef USE_QAPPLICATION
41 static void setExitTask(M method) {
42 if (mt_.exitTask && !mt_.invokeMethod([_p = mt_.exitTask]() { delete _p; }))
delete mt_.exitTask;
43 mt_.exitTask =
new Thread::Task(std::forward<M>(method));
46#ifndef USE_QAPPLICATION
47 if (mt_.running())
return -1;
56#ifdef EXIT_ON_UNIX_SIGNAL
57 if (mt_.eventfd_ >= 0) eventfd_write(mt_.eventfd_, 1);
62 static void exit(
int code) {
67#ifndef USE_QAPPLICATION
70 qApp->exit(mt_.code_);
75 MainThread() :
Thread(
"Main") {
77 setExitTask([]() { quit(); });
78#ifdef USE_QAPPLICATION
80 QObject::connect(qApp, &QCoreApplication::aboutToQuit, [
this]() {
86 qApp->processEvents();
90#ifdef EXIT_ON_UNIX_SIGNAL
91 eventfd_ = eventfd(0, EFD_NONBLOCK);
92 #ifdef USE_QAPPLICATION
95 appendPollTask(eventfd_, AbstractThread::PollIn, [
this](AbstractThread::PollEvents) {
97 if (eventfd_read(eventfd_, &_v) == 0) (*exitTask)();
99 #ifdef USE_QAPPLICATION
106#ifdef EXIT_ON_UNIX_SIGNAL
113 AbstractInstance::List::destroyValues();
115#ifdef USE_QAPPLICATION
116 for (
const std::shared_ptr<Poll> &_n : notifiers) {
delete _n->task; }
117 for (
const Timer &_t : timers) {
delete _t.task; }
120#ifdef USE_QAPPLICATION
126 std::vector<Timer> timers;
128 bool running()
const override {
137 std::vector<Timer>::iterator it = timers.begin();
138 for (; it != timers.end(); ++it, ++
id)
139 if (it->id !=
id)
break;
140 if (msec > 0) { qid = QObject::startTimer(msec); }
141 timers.emplace(it,
Timer {
id, qid, task});
145 virtual bool modifyTimer(
int id,
int msec)
override {
147 for (std::vector<Timer>::iterator it = timers.begin(); it != timers.end(); ++it) {
149 if (it->qid >= 0) QObject::killTimer(it->qid);
150 it->qid = (msec > 0) ? QObject::startTimer(msec) : -1;
161 for (std::vector<Timer>::iterator it = timers.begin(); it != timers.end(); ++it) {
163 if (it->qid >= 0) QObject::killTimer(it->qid);
164 _t =
new Task([p = it->task] { delete p; });
176 void timerEvent(QTimerEvent *e)
override {
177 int qid = e->timerId();
181 for (std::vector<Timer>::iterator it = timers.begin(); it != timers.end(); ++it) {
182 if (it->qid == qid) {
193 if (state_ == 2)
return false;
194 QMetaObject::invokeMethod(
195 const_cast<MainThread *
>(
this),
200 Qt::QueuedConnection);
205 Poll(
int fd) : in(fd, QSocketNotifier::Read), out(fd, QSocketNotifier::Write) {
206 QObject::connect(&in, &QSocketNotifier::activated, [
this]() { (*task)(AbstractThread::PollIn); });
207 QObject::connect(&out, &QSocketNotifier::activated, [
this]() { (*task)(AbstractThread::PollOut); });
217 for (
const std::shared_ptr<Poll> &poll : notifiers)
218 if (poll->in.socket() == fd)
return false;
219 std::shared_ptr<Poll> poll = std::make_shared<Poll>(fd);
220 poll->in.setEnabled(e & AbstractThread::PollIn);
221 poll->out.setEnabled(e & AbstractThread::PollOut);
223 notifiers.append(std::move(poll));
229 for (
const std::shared_ptr<Poll> &poll : notifiers)
230 if (poll->in.socket() == fd) {
231 poll->in.setEnabled(e & AbstractThread::PollIn);
232 poll->out.setEnabled(e & AbstractThread::PollOut);
242 for (
const std::shared_ptr<Poll> &poll : notifiers)
243 if (poll->in.socket() == fd) {
244 _t =
new Task([p = poll->task] { delete p; });
245 notifiers.removeAll(poll);
256 QList<std::shared_ptr<Poll>> notifiers;
260#ifdef EXIT_ON_UNIX_SIGNAL
263#ifdef USE_QAPPLICATION
266 static MainThread mt_;
std::enable_if< std::is_void< typenamestd::invoke_result< M >::type >::value, bool >::type invokeMethod(M method, bool sync=false) const
Runs a method in a managed thread.
Definition AbstractThread.h:74
The MainThread class.
Definition MainThread.h:38