📄 qeventdispatcher_unix.cpp
字号:
}/*! \internal*/bool QEventDispatcherUNIX::unregisterTimers(QObject *object){ if (!object) { qWarning("QEventDispatcherUNIX::unregisterTimers: invalid argument"); return false; } else if (object->thread() != thread() || thread() != QThread::currentThread()) { qWarning("QObject::killTimers: timers cannot be stopped from another thread"); return false; } Q_D(QEventDispatcherUNIX); if (d->timerList.isEmpty()) return false; for (int i = 0; i < d->timerList.size(); ++i) { register QTimerInfo *t = d->timerList.at(i); if (t->obj == object) { // object found d->timerList.removeAt(i); delete t; // move back one so that we don't skip the new current item --i; } } return true;}QList<QEventDispatcherUNIX::TimerInfo>QEventDispatcherUNIX::registeredTimers(QObject *object) const{ if (!object) { qWarning("QEventDispatcherUNIX:registeredTimers: invalid argument"); return QList<TimerInfo>(); } Q_D(const QEventDispatcherUNIX); QList<TimerInfo> list; for (int i = 0; i < d->timerList.size(); ++i) { register const QTimerInfo * const t = d->timerList.at(i); if (t->obj == object) list << TimerInfo(t->id, t->interval.tv_sec * 1000 + t->interval.tv_usec / 1000); } return list;}/***************************************************************************** Socket notifier type *****************************************************************************/QSockNotType::QSockNotType(){ FD_ZERO(&select_fds); FD_ZERO(&enabled_fds); FD_ZERO(&pending_fds);}QSockNotType::~QSockNotType(){ while (!list.isEmpty()) delete list.takeFirst();}/***************************************************************************** QEventDispatcher implementations for UNIX *****************************************************************************/void QEventDispatcherUNIX::registerSocketNotifier(QSocketNotifier *notifier){ int sockfd; int type; if (!notifier || (sockfd = notifier->socket()) < 0 || sockfd > FD_SETSIZE || (type = notifier->type()) < 0 || type > 2) { qWarning("QSocketNotifier: Internal error"); return; } else if (notifier->thread() != thread() || thread() != QThread::currentThread()) { qWarning("QSocketNotifier: socket notifiers cannot be enabled from another thread"); return; } Q_D(QEventDispatcherUNIX); QList<QSockNot *> &list = d->sn_vec[type].list; fd_set *fds = &d->sn_vec[type].enabled_fds; QSockNot *sn; sn = new QSockNot; sn->obj = notifier; sn->fd = sockfd; sn->queue = &d->sn_vec[type].pending_fds; int i; for (i = 0; i < list.size(); ++i) { QSockNot *p = list.at(i); if (p->fd < sockfd) break; if (p->fd == sockfd) { static const char *t[] = { "read", "write", "exception" }; qWarning("QSocketNotifier: Multiple socket notifiers for " "same socket %d and type %s", sockfd, t[type]); } } list.insert(i, sn); FD_SET(sockfd, fds); d->sn_highest = qMax(d->sn_highest, sockfd);}void QEventDispatcherUNIX::unregisterSocketNotifier(QSocketNotifier *notifier){ int sockfd; int type; if (!notifier || (sockfd = notifier->socket()) < 0 || sockfd > FD_SETSIZE || (type = notifier->type()) < 0 || type > 2) { qWarning("QSocketNotifier: Internal error"); return; } else if (notifier->thread() != thread() || thread() != QThread::currentThread()) { qWarning("QSocketNotifier: socket notifiers cannot be disabled from another thread"); return; } Q_D(QEventDispatcherUNIX); QList<QSockNot *> &list = d->sn_vec[type].list; fd_set *fds = &d->sn_vec[type].enabled_fds; QSockNot *sn; int i; for (i = 0; i < list.size(); ++i) { sn = list.at(i); if(sn->obj == notifier && sn->fd == sockfd) break; } if (i == list.size()) // not found return; FD_CLR(sockfd, fds); // clear fd bit FD_CLR(sockfd, sn->queue); d->sn_pending_list.removeAll(sn); // remove from activation list list.removeAt(i); // remove notifier found above delete sn; if (d->sn_highest == sockfd) { // find highest fd d->sn_highest = -1; for (int i=0; i<3; i++) { if (!d->sn_vec[i].list.isEmpty()) d->sn_highest = qMax(d->sn_highest, // list is fd-sorted d->sn_vec[i].list.first()->fd); } }}void QEventDispatcherUNIX::setSocketNotifierPending(QSocketNotifier *notifier){ int sockfd; int type; if (!notifier || (sockfd = notifier->socket()) < 0 || sockfd > FD_SETSIZE || (type = notifier->type()) < 0 || type > 2) { qWarning("QSocketNotifier: Internal error"); return; } Q_ASSERT(notifier->thread() == thread() && thread() == QThread::currentThread()); Q_D(QEventDispatcherUNIX); QList<QSockNot *> &list = d->sn_vec[type].list; QSockNot *sn = 0; int i; for (i = 0; i < list.size(); ++i) { sn = list.at(i); if(sn->obj == notifier && sn->fd == sockfd) break; } if (i == list.size()) // not found return; // We choose a random activation order to be more fair under high load. // If a constant order is used and a peer early in the list can // saturate the IO, it might grab our attention completely. // Also, if we're using a straight list, the callback routines may // delete other entries from the list before those other entries are // processed. if (! FD_ISSET(sn->fd, sn->queue)) { d->sn_pending_list.insert((rand() & 0xff) % (d->sn_pending_list.size()+1), sn); FD_SET(sn->fd, sn->queue); }}int QEventDispatcherUNIX::activateTimers(){ Q_ASSERT(thread() == QThread::currentThread()); Q_D(QEventDispatcherUNIX); if (qt_disable_lowpriority_timers || d->timerList.isEmpty()) return 0; // nothing to do bool first = true; timeval currentTime; int n_act = 0, maxCount = d->timerList.size(); QTimerInfo *begin = 0; while (maxCount--) { getTime(currentTime); if (first) { if (currentTime < d->watchtime) d->timerRepair(currentTime); // clock was turned back first = false; d->watchtime = currentTime; } if (d->timerList.isEmpty()) break; register QTimerInfo *t = d->timerList.first(); if (currentTime < t->timeout) break; // no timer has expired if (!begin) { begin = t; } else if (begin == t) { // avoid sending the same timer multiple times break; } else if (t->interval < begin->interval || t->interval == begin->interval) { begin = t; } // remove from list d->timerList.removeFirst(); t->timeout += t->interval; if (t->timeout < currentTime) t->timeout = currentTime + t->interval; // reinsert timer d->timerInsert(t); if (t->interval.tv_usec > 0 || t->interval.tv_sec > 0) n_act++; // send event QTimerEvent e(t->id); QCoreApplication::sendEvent(t->obj, &e); if (!d->timerList.contains(begin)) begin = 0; } return n_act;}int QEventDispatcherUNIX::activateSocketNotifiers(){ Q_D(QEventDispatcherUNIX); if (d->sn_pending_list.isEmpty()) return 0; // create sets that match the current pending sets (note: we skip // the first one, because we activate first and check second) fd_set rset, wset, xset; FD_ZERO(&rset); FD_ZERO(&wset); FD_ZERO(&xset); for (int i = 1; i < d->sn_pending_list.size(); ++i) { const QSockNot * const sn = d->sn_pending_list.at(i); switch (sn->obj->type()) { case QSocketNotifier::Read: FD_SET(sn->fd, &rset); break; case QSocketNotifier::Write: FD_SET(sn->fd, &wset); break; case QSocketNotifier::Exception: FD_SET(sn->fd, &xset); break; } } // activate entries int n_act = 0; QEvent event(QEvent::SockAct); while (!d->sn_pending_list.isEmpty()) { QSockNot *sn = d->sn_pending_list.takeFirst(); if (FD_ISSET(sn->fd, sn->queue)) { FD_CLR(sn->fd, sn->queue); QCoreApplication::sendEvent(sn->obj, &event); n_act++; } if (d->sn_pending_list.isEmpty()) break; // check if any fds are no longer pending int ret = -1; do { timeval zero_timeout = { 0l, 0l }; ret = ::select(d->sn_highest + 1, &rset, &wset, &xset, &zero_timeout); } while (ret == -1 && (errno == EINTR || errno == EAGAIN)); if (ret < -1) { // any errors caught here are new errors, so we punt and // let doSelect() handle them break; } for (int i = 0; i < d->sn_pending_list.size(); ++i) { QSockNot *sn = d->sn_pending_list.at(i); fd_set *set = 0; switch (sn->obj->type()) { case QSocketNotifier::Read: set = &rset; break; case QSocketNotifier::Write: set = &wset; break; case QSocketNotifier::Exception: set = &xset; break; } if (set && !FD_ISSET(sn->fd, set)) { // fd is no longer pending FD_CLR(sn->fd, set); FD_CLR(sn->fd, sn->queue); d->sn_pending_list.removeAt(i--); } } } return n_act;}bool QEventDispatcherUNIX::processEvents(QEventLoop::ProcessEventsFlags flags){ Q_D(QEventDispatcherUNIX); d->interrupt = false; // we are awake, broadcast it emit awake(); QCoreApplication::sendPostedEvents(0, (flags & QEventLoop::DeferredDeletion) ? -1 : 0); int nevents = 0; QThreadData *data = QThreadData::get(thread()); const bool canWait = (data->canWait && !d->interrupt && (flags & QEventLoop::WaitForMoreEvents)); if (canWait) emit aboutToBlock(); if (!d->interrupt) { // return the maximum time we can wait for an event. timeval *tm = 0; timeval wait_tm = { 0l, 0l }; if (!(flags & QEventLoop::X11ExcludeTimers)) { if (d->timerWait(wait_tm)) tm = &wait_tm; if (!canWait) { if (!tm) tm = &wait_tm; // no time to wait tm->tv_sec = 0l; tm->tv_usec = 0l; } } nevents = d->doSelect(flags, tm); // activate timers if (! (flags & QEventLoop::X11ExcludeTimers)) { nevents += activateTimers(); } } // return true if we handled events, false otherwise return (nevents > 0);}bool QEventDispatcherUNIX::hasPendingEvents(){ extern uint qGlobalPostedEventsCount(); // from qapplication.cpp return qGlobalPostedEventsCount();}void QEventDispatcherUNIX::wakeUp(){ Q_D(QEventDispatcherUNIX); if (d->wakeUps.testAndSet(0, 1)) { char c = 0; ::write( d->thread_pipe[1], &c, 1 ); }}void QEventDispatcherUNIX::interrupt(){ Q_D(QEventDispatcherUNIX); d->interrupt = true; wakeUp();}void QEventDispatcherUNIX::flush(){ }void QCoreApplication::watchUnixSignal(int sig, bool watch){ if (sig < NSIG) { struct sigaction sa; sigemptyset(&(sa.sa_mask)); sa.sa_flags = 0; if (watch) sa.sa_handler = signalHandler; else sa.sa_handler = SIG_DFL; sigaction(sig, &sa, 0); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -