📄 qeventdispatcher_unix.cpp
字号:
if (t->obj == object) { // object found removeAt(i); if (t == firstTimerInfo) firstTimerInfo = 0; if (t == currentTimerInfo) currentTimerInfo = 0; delete t; // move back one so that we don't skip the new current item --i; } } return true;}QList<QPair<int, int> > QTimerInfoList::registeredTimers(QObject *object) const{ QList<QPair<int, int> > list; for (int i = 0; i < count(); ++i) { register const QTimerInfo * const t = at(i); if (t->obj == object) list << QPair<int, int>(t->id, t->interval.tv_sec * 1000 + t->interval.tv_usec / 1000); } return list;}/* Activate pending timers, returning how many where activated.*/int QTimerInfoList::activateTimers(){ if (qt_disable_lowpriority_timers || isEmpty()) return 0; // nothing to do bool firstTime = true; timeval currentTime; int n_act = 0, maxCount = count(); QTimerInfo *saveFirstTimerInfo = firstTimerInfo; QTimerInfo *saveCurrentTimerInfo = currentTimerInfo; firstTimerInfo = currentTimerInfo = 0; while (maxCount--) { currentTime = updateCurrentTime(); if (firstTime) { repairTimersIfNeeded(); firstTime = false; } if (isEmpty()) break; currentTimerInfo = first(); if (currentTime < currentTimerInfo->timeout) break; // no timer has expired if (!firstTimerInfo) { firstTimerInfo = currentTimerInfo; } else if (firstTimerInfo == currentTimerInfo) { // avoid sending the same timer multiple times break; } else if (currentTimerInfo->interval < firstTimerInfo->interval || currentTimerInfo->interval == firstTimerInfo->interval) { firstTimerInfo = currentTimerInfo; } // remove from list removeFirst(); // determine next timeout time currentTimerInfo->timeout += currentTimerInfo->interval; if (currentTimerInfo->timeout < currentTime) currentTimerInfo->timeout = currentTime + currentTimerInfo->interval; // reinsert timer timerInsert(currentTimerInfo); if (currentTimerInfo->interval.tv_usec > 0 || currentTimerInfo->interval.tv_sec > 0) n_act++; if (!currentTimerInfo->inTimerEvent) { // send event, but don't allow it to recurse currentTimerInfo->inTimerEvent = true; QTimerEvent e(currentTimerInfo->id); QCoreApplication::sendEvent(currentTimerInfo->obj, &e); if (currentTimerInfo) currentTimerInfo->inTimerEvent = false; } } firstTimerInfo = saveFirstTimerInfo; currentTimerInfo = saveCurrentTimerInfo; return n_act;}QEventDispatcherUNIX::QEventDispatcherUNIX(QObject *parent) : QAbstractEventDispatcher(*new QEventDispatcherUNIXPrivate, parent){ }QEventDispatcherUNIX::QEventDispatcherUNIX(QEventDispatcherUNIXPrivate &dd, QObject *parent) : QAbstractEventDispatcher(dd, parent){ }QEventDispatcherUNIX::~QEventDispatcherUNIX(){ }int QEventDispatcherUNIX::select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, timeval *timeout){ Q_D(QEventDispatcherUNIX); if (timeout) { // handle the case where select returns with a timeout, too // soon. timeval tvStart = d->timerList.currentTime; timeval tvCurrent = tvStart; timeval originalTimeout = *timeout; int nsel; do { timeval tvRest = originalTimeout + tvStart - tvCurrent; nsel = ::select(nfds, readfds, writefds, exceptfds, &tvRest); d->timerList.getTime(tvCurrent); } while (nsel == 0 && (tvCurrent - tvStart) < originalTimeout); return nsel; } return ::select(nfds, readfds, writefds, exceptfds, timeout);}/*! \internal*/void QEventDispatcherUNIX::registerTimer(int timerId, int interval, QObject *obj){#ifndef QT_NO_DEBUG if (timerId < 1 || interval < 0 || !obj) { qWarning("QEventDispatcherUNIX::registerTimer: invalid arguments"); return; } else if (obj->thread() != thread() || thread() != QThread::currentThread()) { qWarning("QObject::startTimer: timers cannot be started from another thread"); return; }#endif Q_D(QEventDispatcherUNIX); d->timerList.registerTimer(timerId, interval, obj);}/*! \internal*/bool QEventDispatcherUNIX::unregisterTimer(int timerId){#ifndef QT_NO_DEBUG if (timerId < 1) { qWarning("QEventDispatcherUNIX::unregisterTimer: invalid argument"); return false; } else if (thread() != QThread::currentThread()) { qWarning("QObject::killTimer: timers cannot be stopped from another thread"); return false; }#endif Q_D(QEventDispatcherUNIX); return d->timerList.unregisterTimer(timerId);}/*! \internal*/bool QEventDispatcherUNIX::unregisterTimers(QObject *object){#ifndef QT_NO_DEBUG 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; }#endif Q_D(QEventDispatcherUNIX); return d->timerList.unregisterTimers(object);}QList<QEventDispatcherUNIX::TimerInfo>QEventDispatcherUNIX::registeredTimers(QObject *object) const{ if (!object) { qWarning("QEventDispatcherUNIX:registeredTimers: invalid argument"); return QList<TimerInfo>(); } Q_D(const QEventDispatcherUNIX); return d->timerList.registeredTimers(object);}/***************************************************************************** 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){ Q_ASSERT(notifier); int sockfd = notifier->socket(); int type = notifier->type();#ifndef QT_NO_DEBUG if (sockfd < 0 || unsigned(sockfd) >= FD_SETSIZE) { qWarning("QSocketNotifier: Internal error"); return; } else if (notifier->thread() != thread() || thread() != QThread::currentThread()) { qWarning("QSocketNotifier: socket notifiers cannot be enabled from another thread"); return; }#endif Q_D(QEventDispatcherUNIX); QSockNotType::List &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){ Q_ASSERT(notifier); int sockfd = notifier->socket(); int type = notifier->type();#ifndef QT_NO_DEBUG if (sockfd < 0 || unsigned(sockfd) >= FD_SETSIZE) { qWarning("QSocketNotifier: Internal error"); return; } else if (notifier->thread() != thread() || thread() != QThread::currentThread()) { qWarning("QSocketNotifier: socket notifiers cannot be disabled from another thread"); return; }#endif Q_D(QEventDispatcherUNIX); QSockNotType::List &list = d->sn_vec[type].list; fd_set *fds = &d->sn_vec[type].enabled_fds; 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; 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){ Q_ASSERT(notifier); int sockfd = notifier->socket(); int type = notifier->type();#ifndef QT_NO_DEBUG if (sockfd < 0 || unsigned(sockfd) >= FD_SETSIZE) { qWarning("QSocketNotifier: Internal error"); return; } Q_ASSERT(notifier->thread() == thread() && thread() == QThread::currentThread());#endif Q_D(QEventDispatcherUNIX); QSockNotType::List &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)) { if (d->sn_pending_list.isEmpty()) { d->sn_pending_list.append(sn); } else { d->sn_pending_list.insert((qrand() & 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); return d->timerList.activateTimers();}int QEventDispatcherUNIX::activateSocketNotifiers(){ Q_D(QEventDispatcherUNIX); if (d->sn_pending_list.isEmpty()) return 0; // 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; } } return n_act;}bool QEventDispatcherUNIX::processEvents(QEventLoop::ProcessEventsFlags flags){ Q_D(QEventDispatcherUNIX); d->interrupt = false; // we are awake, broadcast it emit awake(); QCoreApplicationPrivate::sendPostedEvents(0, (flags & QEventLoop::DeferredDeletion) ? -1 : 0, d->threadData); int nevents = 0; const bool canWait = (d->threadData->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->timerList.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.testAndSetAcquire(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 + -