⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 qeventdispatcher_unix.cpp

📁 qt-x11-opensource-src-4.1.4.tar.gz源码
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/******************************************************************************** Copyright (C) 1992-2006 Trolltech ASA. All rights reserved.**** This file is part of the QtCore module of the Qt Toolkit.**** This file may be used under the terms of the GNU General Public** License version 2.0 as published by the Free Software Foundation** and appearing in the file LICENSE.GPL included in the packaging of** this file.  Please review the following information to ensure GNU** General Public Licensing requirements will be met:** http://www.trolltech.com/products/qt/opensource.html**** If you are unsure which license is appropriate for your use, please** review the following information:** http://www.trolltech.com/products/qt/licensing.html or contact the** sales department at sales@trolltech.com.**** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.******************************************************************************/#include "qplatformdefs.h"#include "qcoreapplication.h"#include "qpair.h"#include "qsocketnotifier.h"#include "qthread.h"#include "qeventdispatcher_unix_p.h"#include <private/qthread_p.h>#include <errno.h>#include <stdio.h>#include <stdlib.h>Q_CORE_EXPORT bool qt_disable_lowpriority_timers=false;// Internal operator functions for timevalsstatic inline bool operator<(const timeval &t1, const timeval &t2){ return t1.tv_sec < t2.tv_sec || (t1.tv_sec == t2.tv_sec && t1.tv_usec < t2.tv_usec); }static inline bool operator==(const timeval &t1, const timeval &t2){ return t1.tv_sec == t2.tv_sec && t1.tv_usec == t2.tv_usec; }static inline timeval &operator+=(timeval &t1, const timeval &t2){    t1.tv_sec += t2.tv_sec;    if ((t1.tv_usec += t2.tv_usec) >= 1000000l) {        ++t1.tv_sec;        t1.tv_usec -= 1000000l;    }    return t1;}static inline timeval operator+(const timeval &t1, const timeval &t2){    timeval tmp;    tmp.tv_sec = t1.tv_sec + t2.tv_sec;    if ((tmp.tv_usec = t1.tv_usec + t2.tv_usec) >= 1000000l) {        ++tmp.tv_sec;        tmp.tv_usec -= 1000000l;    }    return tmp;}static inline timeval operator-(const timeval &t1, const timeval &t2){    timeval tmp;    tmp.tv_sec = t1.tv_sec - t2.tv_sec;    if ((tmp.tv_usec = t1.tv_usec - t2.tv_usec) < 0l) {        --tmp.tv_sec;        tmp.tv_usec += 1000000l;    }    return tmp;}// get time of daystatic inline void getTime(timeval &t){    gettimeofday(&t, 0);    // NTP-related fix    while (t.tv_usec >= 1000000l) {        t.tv_usec -= 1000000l;        ++t.tv_sec;    }    while (t.tv_usec < 0l) {        if (t.tv_sec > 0l) {            t.tv_usec += 1000000l;            --t.tv_sec;        } else {            t.tv_usec = 0l;            break;        }    }}struct QTimerInfo {    int id;           // - timer identifier    timeval interval; // - timer interval    timeval timeout;  // - when to sent event    QObject *obj;     // - object to receive event};/***************************************************************************** UNIX signal handling *****************************************************************************/static sig_atomic_t signal_received;static sig_atomic_t signals_fired[NSIG];static void signalHandler(int sig){    signals_fired[sig] = 1;    signal_received = 1;}QEventDispatcherUNIXPrivate::QEventDispatcherUNIXPrivate(){    extern Qt::HANDLE qt_application_thread_id;    mainThread = (QThread::currentThreadId() == qt_application_thread_id);    // initialize the common parts of the event loop    pipe(thread_pipe);    fcntl(thread_pipe[0], F_SETFD, FD_CLOEXEC);    fcntl(thread_pipe[1], F_SETFD, FD_CLOEXEC);    fcntl(thread_pipe[0], F_SETFL, fcntl(thread_pipe[0], F_GETFL) | O_NONBLOCK);    fcntl(thread_pipe[1], F_SETFL, fcntl(thread_pipe[1], F_GETFL) | O_NONBLOCK);    sn_highest = -1;    interrupt = false;    getTime(watchtime);}QEventDispatcherUNIXPrivate::~QEventDispatcherUNIXPrivate(){    // cleanup the common parts of the event loop    close(thread_pipe[0]);    close(thread_pipe[1]);    // cleanup timers    qDeleteAll(timerList);}int QEventDispatcherUNIXPrivate::doSelect(QEventLoop::ProcessEventsFlags flags, timeval *timeout){    Q_Q(QEventDispatcherUNIX);    int nsel;    do {        if (mainThread) {            while (signal_received) {                signal_received = 0;                for (int i = 0; i < NSIG; ++i) {                    if (signals_fired[i]) {                        signals_fired[i] = 0;                        emit QCoreApplication::instance()->unixSignal(i);                    }                }            }        }        // Process timers and socket notifiers - the common UNIX stuff        int highest = 0;        FD_ZERO(&sn_vec[0].select_fds);        FD_ZERO(&sn_vec[1].select_fds);        FD_ZERO(&sn_vec[2].select_fds);        if (! (flags & QEventLoop::ExcludeSocketNotifiers) && (sn_highest >= 0)) {            // return the highest fd we can wait for input on            if (!sn_vec[0].list.isEmpty())                sn_vec[0].select_fds = sn_vec[0].enabled_fds;            if (!sn_vec[1].list.isEmpty())                sn_vec[1].select_fds = sn_vec[1].enabled_fds;            if (!sn_vec[2].list.isEmpty())                sn_vec[2].select_fds = sn_vec[2].enabled_fds;            highest = sn_highest;        }        FD_SET(thread_pipe[0], &sn_vec[0].select_fds);        highest = qMax(highest, thread_pipe[0]);        nsel = q->select(highest + 1,                         &sn_vec[0].select_fds,                         &sn_vec[1].select_fds,                         &sn_vec[2].select_fds,                         timeout);    } while (nsel == -1 && (errno == EINTR || errno == EAGAIN));    if (nsel == -1) {        if (errno == EBADF) {            // it seems a socket notifier has a bad fd... find out            // which one it is and disable it            fd_set fdset;            timeval tm;            tm.tv_sec = tm.tv_usec = 0l;            for (int type = 0; type < 3; ++type) {                QList<QSockNot *> &list = sn_vec[type].list;                if (list.size() == 0)                    continue;                for (int i = 0; i < list.size(); ++i) {                    QSockNot *sn = list.at(i);                    FD_ZERO(&fdset);                    FD_SET(sn->fd, &fdset);                    int ret = -1;                    do {                        switch (type) {                        case 0: // read                            ret = select(sn->fd + 1, &fdset, 0, 0, &tm);                            break;                        case 1: // write                            ret = select(sn->fd + 1, 0, &fdset, 0, &tm);                            break;                        case 2: // except                            ret = select(sn->fd + 1, 0, 0, &fdset, &tm);                            break;                        }                    } while (ret == -1 && (errno == EINTR || errno == EAGAIN));                    if (ret == -1 && errno == EBADF) {                        // disable the invalid socket notifier                        static const char *t[] = { "Read", "Write", "Exception" };                        qWarning("QSocketNotifier: invalid socket %d and type '%s', disabling...",                                 sn->fd, t[type]);                        sn->obj->setEnabled(false);                    }                }            }        } else {            // EINVAL... shouldn't happen, so let's complain to stderr            // and hope someone sends us a bug report            perror("select");        }    }    // some other thread woke us up... consume the data on the thread pipe so that    // select doesn't immediately return next time    int nevents = 0;    if (nsel > 0 && FD_ISSET(thread_pipe[0], &sn_vec[0].select_fds)) {        char c[16];        while (::read(thread_pipe[0], c, sizeof(c)) > 0)            ;        wakeUps = 0;        ++nevents;    }    // activate socket notifiers    if (! (flags & QEventLoop::ExcludeSocketNotifiers) && nsel > 0 && sn_highest >= 0) {        // if select says data is ready on any socket, then set the socket notifier        // to pending        for (int i=0; i<3; i++) {            QList<QSockNot *> &list = sn_vec[i].list;            for (int j = 0; j < list.size(); ++j) {                QSockNot *sn = list.at(j);                if (FD_ISSET(sn->fd, &sn_vec[i].select_fds))                    q->setSocketNotifierPending(sn->obj);            }        }    }    return (nevents + q->activateSocketNotifiers());}/* * Internal functions for manipulating timer data structures.  The * timerBitVec array is used for keeping track of timer identifiers. *//*  insert timer info into list*/ void QEventDispatcherUNIXPrivate::timerInsert(QTimerInfo *ti){    int index = 0;#if defined(QT_DEBUG)    int dangerCount = 0;#endif    for (; index < timerList.size(); ++index) {        register const QTimerInfo * const t = timerList.at(index);#if defined(QT_DEBUG)        if (t->obj == ti->obj) ++dangerCount;#endif        if (ti->timeout < t->timeout) break;    }    timerList.insert(index, ti);#if defined(QT_DEBUG)    if (dangerCount > 16)        qDebug("QObject: %d timers now exist for object %s::%s",               dangerCount, ti->obj->metaObject()->className(),               ti->obj->objectName().toLocal8Bit().data());#endif}/*  repair broken timer*/void QEventDispatcherUNIXPrivate::timerRepair(const timeval &time){    timeval diff = watchtime - time;    // repair all timers    for (int i = 0; i < timerList.size(); ++i) {        register QTimerInfo *t = timerList.at(i);        t->timeout = t->timeout - diff;    }}/*  Returns the time to wait for the next timer, or null if no timers  are waiting.*/bool QEventDispatcherUNIXPrivate::timerWait(timeval &tm){    timeval currentTime;    getTime(currentTime);    if (currentTime < watchtime)        // clock was turned back        timerRepair(currentTime);    watchtime = currentTime;    if (timerList.isEmpty())        return false;    QTimerInfo *t = timerList.first();        // first waiting timer    if (currentTime < t->timeout) {        // time to wait        tm = t->timeout - currentTime;    } else {        // no time to wait        tm.tv_sec  = 0;        tm.tv_usec = 0;    }    return true;}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->watchtime;        timeval tvCurrent = tvStart;        timeval originalTimeout = *timeout;        int nsel;        do {            timeval tvRest = originalTimeout + tvStart - tvCurrent;            nsel = ::select(nfds, readfds, writefds, exceptfds, &tvRest);            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){    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;    }    QTimerInfo *t = new QTimerInfo;                // create timer    t->id = timerId;    t->interval.tv_sec  = interval / 1000;    t->interval.tv_usec = (interval % 1000) * 1000;    timeval currentTime;    getTime(currentTime);    t->timeout = currentTime + t->interval;    t->obj = obj;    Q_D(QEventDispatcherUNIX);    d->timerInsert(t);                                // put timer in list}/*!    \internal*/bool QEventDispatcherUNIX::unregisterTimer(int timerId){    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;    }    Q_D(QEventDispatcherUNIX);    // set timer inactive    for (int i = 0; i < d->timerList.size(); ++i) {        register QTimerInfo *t = d->timerList.at(i);        if (t->id == timerId) {            d->timerList.removeAt(i);            delete t;            return true;        }    }    // id not found    return false;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -