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

📄 qeventdispatcher_unix.cpp

📁 奇趣公司比较新的qt/emd版本
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/******************************************************************************** Copyright (C) 1992-2007 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://trolltech.com/products/qt/licenses/licensing/opensource/**** If you are unsure which license is appropriate for your use, please** review the following information:** http://trolltech.com/products/qt/licenses/licensing/licensingoverview** or contact the sales department at sales@trolltech.com.**** In addition, as a special exception, Trolltech gives you certain** additional rights. These rights are described in the Trolltech GPL** Exception version 1.0, which can be found at** http://www.trolltech.com/products/qt/gplexception/ and in the file** GPL_EXCEPTION.txt in this package.**** In addition, as a special exception, Trolltech, as the sole copyright** holder for Qt Designer, grants users of the Qt/Eclipse Integration** plug-in the right for the Qt/Eclipse Integration to link to** functionality provided by Qt Designer and its related libraries.**** Trolltech reserves all rights not expressly granted herein.**** 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 <private/qcoreapplication_p.h>#include <errno.h>#include <stdio.h>#include <stdlib.h>#if (_POSIX_MONOTONIC_CLOCK-0 <= 0)#  include <sys/times.h>#endifQ_CORE_EXPORT bool qt_disable_lowpriority_timers=false;/***************************************************************************** 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;}static void initThreadPipeFD(int fd){    int ret = fcntl(fd, F_SETFD, FD_CLOEXEC);    if (ret == -1)        perror("QEventDispatcherUNIXPrivate: Unable to init thread pipe");    int flags = fcntl(fd, F_GETFL);    if (flags == -1)        perror("QEventDispatcherUNIXPrivate: Unable to get flags on thread pipe");    ret = fcntl(fd, F_SETFL, flags | O_NONBLOCK);    if (ret == -1)        perror("QEventDispatcherUNIXPrivate: Unable to set flags on thread pipe");}QEventDispatcherUNIXPrivate::QEventDispatcherUNIXPrivate(){    extern Qt::HANDLE qt_application_thread_id;    mainThread = (QThread::currentThreadId() == qt_application_thread_id);    // initialize the common parts of the event loop#ifdef Q_OS_INTEGRITY    // INTEGRITY doesn't like a "select" on pipes, so use socketpair instead    if (socketpair(AF_INET, SOCK_STREAM, PF_INET, thread_pipe) == -1)        perror("QEventDispatcherUNIXPrivate(): Unable to create socket pair");#else    if (pipe(thread_pipe) == -1)        perror("QEventDispatcherUNIXPrivate(): Unable to create thread pipe");#endif    initThreadPipeFD(thread_pipe[0]);    initThreadPipeFD(thread_pipe[1]);    sn_highest = -1;    interrupt = false;}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);    // needed in QEventDispatcherUNIX::select()    timerList.updateCurrentTime();    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;        if (! (flags & QEventLoop::ExcludeSocketNotifiers) && (sn_highest >= 0)) {            // return the highest fd we can wait for input on                sn_vec[0].select_fds = sn_vec[0].enabled_fds;                sn_vec[1].select_fds = sn_vec[1].enabled_fds;                sn_vec[2].select_fds = sn_vec[2].enabled_fds;            highest = sn_highest;        } else {            FD_ZERO(&sn_vec[0].select_fds);            FD_ZERO(&sn_vec[1].select_fds);            FD_ZERO(&sn_vec[2].select_fds);        }        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) {                QSockNotType::List &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)            ;        if (!wakeUps.testAndSetRelease(1, 0)) {            // hopefully, this is dead code            qWarning("QEventDispatcherUNIX: internal error, wakeUps.testAndSetRelease(1, 0) failed!");        }        ++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++) {            QSockNotType::List &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. */QTimerInfoList::QTimerInfoList(){#if (_POSIX_MONOTONIC_CLOCK-0 <= 0)    useMonotonicTimers = false;#  if (_POSIX_MONOTONIC_CLOCK == 0)    // detect if the system support monotonic timers    long x = sysconf(_SC_MONOTONIC_CLOCK);    useMonotonicTimers = x >= 200112L;#  endif    getTime(currentTime);    if (!useMonotonicTimers) {        // not using monotonic timers, initialize the timeChanged() machinery        previousTime = currentTime;        tms unused;        previousTicks = times(&unused);        ticksPerSecond = sysconf(_SC_CLK_TCK);        msPerTick = 1000/ticksPerSecond;    } else {        // detected monotonic timers        previousTime.tv_sec = previousTime.tv_usec = 0;        previousTicks = 0;        ticksPerSecond = 0;        msPerTick = 0;    }#else    // using monotonic timers unconditionally    getTime(currentTime);#endif    firstTimerInfo = currentTimerInfo = 0;}timeval QTimerInfoList::updateCurrentTime(){    getTime(currentTime);    return currentTime;}#if (_POSIX_MONOTONIC_CLOCK-0 > 0)void QTimerInfoList::getTime(timeval &t){    timespec ts;    clock_gettime(CLOCK_MONOTONIC, &ts);    t.tv_sec = ts.tv_sec;    t.tv_usec = ts.tv_nsec / 1000;}void QTimerInfoList::repairTimersIfNeeded(){}#else/*  Returns true if the real time clock has changed by more than 10%  relative to the processor time since the last time this function was  called. This presumably means that the system time has been changed.  If /a delta is nonzero, delta is set to our best guess at how much the system clock was changed.*/bool QTimerInfoList::timeChanged(timeval *delta){    tms unused;    clock_t currentTicks = times(&unused);    int elapsedTicks = currentTicks - previousTicks;    timeval elapsedTime = currentTime - previousTime;    int elapsedMsecTicks = (elapsedTicks * 1000) / ticksPerSecond;    int deltaMsecs = (elapsedTime.tv_sec * 1000 + elapsedTime.tv_usec / 1000)                     - elapsedMsecTicks;    if (delta) {	delta->tv_sec = deltaMsecs / 1000;	delta->tv_usec = (deltaMsecs % 1000) * 1000;    }    previousTicks = currentTicks;    previousTime = currentTime;    // If tick drift is more than 10% off compared to realtime, we assume that the clock has    // been set. Of course, we have to allow for the tick granularity as well.     return (qAbs(deltaMsecs) - msPerTick) * 10 > elapsedMsecTicks;}void QTimerInfoList::getTime(timeval &t){#if !defined(QT_NO_CLOCK_MONOTONIC)    if (useMonotonicTimers) {        timespec ts;        clock_gettime(CLOCK_MONOTONIC, &ts);        t.tv_sec = ts.tv_sec;        t.tv_usec = ts.tv_nsec / 1000;        return;    }#endif    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;        }    }}void QTimerInfoList::repairTimersIfNeeded(){    if (useMonotonicTimers)        return;    timeval delta;    if (timeChanged(&delta))        timerRepair(delta);}#endif/*  insert timer info into list*/void QTimerInfoList::timerInsert(QTimerInfo *ti){    int index = size();    while (index--) {        register const QTimerInfo * const t = at(index);        if (!(ti->timeout < t->timeout))            break;    }    insert(index+1, ti);}/*  repair broken timer*/void QTimerInfoList::timerRepair(const timeval &diff){    // repair all timers    for (int i = 0; i < size(); ++i) {        register QTimerInfo *t = at(i);        t->timeout = t->timeout - diff;    }}/*  Returns the time to wait for the next timer, or null if no timers  are waiting.*/bool QTimerInfoList::timerWait(timeval &tm){    timeval currentTime = updateCurrentTime();    repairTimersIfNeeded();    if (isEmpty())        return false;    QTimerInfo *t = 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;}void QTimerInfoList::registerTimer(int timerId, int interval, QObject *object){    QTimerInfo *t = new QTimerInfo;    t->id = timerId;    t->interval.tv_sec  = interval / 1000;    t->interval.tv_usec = (interval % 1000) * 1000;    t->timeout = updateCurrentTime() + t->interval;    t->obj = object;    t->inTimerEvent = false;    timerInsert(t);}bool QTimerInfoList::unregisterTimer(int timerId){    // set timer inactive    for (int i = 0; i < count(); ++i) {        register QTimerInfo *t = at(i);        if (t->id == timerId) {            removeAt(i);            if (t == firstTimerInfo)                firstTimerInfo = 0;            if (t == currentTimerInfo)                currentTimerInfo = 0;            delete t;            return true;        }    }    // id not found    return false;}bool QTimerInfoList::unregisterTimers(QObject *object){    if (isEmpty())        return false;    for (int i = 0; i < count(); ++i) {        register QTimerInfo *t = at(i);

⌨️ 快捷键说明

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