QT多线程系统分析QThread

 

QT多线程系统分析QThread

比赛推迟到了明天,今晚还要继续早点休息了。今天的天气突然变得特别冷,真不敢想象明天早上六点五十要在校门口集合是一个什么感觉。

好了,现在开始今天的分析,我们从QThread类开始。路径corelib/thread/thread.h。在QThread类中引用了

class QThreadData;

class QThreadPrivate;

首先该类提供了几个静态方法:

static Qt::HANDLE currentThreadId();

    static QThread *currentThread();

    static int idealThreadCount();

    static void yieldCurrentThread();

接下来提供了线程优先级的枚举类型:

enum Priority {

        IdlePriority,

 

        LowestPriority,

        LowPriority,

        NormalPriority,

        HighPriority,

        HighestPriority,

 

        TimeCriticalPriority,

 

        InheritPriority

    };

分别为:空闲时、最低、低、正常、高、最高、立即方式、继承父类优先级。

另一个比较有用的函数是void setStackSize(uint stackSize);如果在线程中进行递归调用,那么可以通过增加堆得大小来保证递归不会溢出。

剩下是几个函数是我们经常见到的了:

void start(Priority = InheritPriority);

    void terminate();

    void quit();

 

public:

    // default argument causes thread to block indefinately

    bool wait(unsigned long time = ULONG_MAX);

 

Q_SIGNALS:

    void started();

    void finished();

    void terminated();

 

protected:

    virtual void run();

    int exec();

 

    static void setTerminationEnabled(bool enabled = true);

 

    static void sleep(unsigned long);

    static void msleep(unsigned long);

    static void usleep(unsigned long);

static void initialize();

    static void cleanup();

 

    friend class QCoreApplication;

    friend class QThreadData;

       当定义为QT_NO_THREAD时,该类将只为内部主线程使用:

class Q_CORE_EXPORT QThread : public QObject

{

public:

    static Qt::HANDLE currentThreadId() { return Qt::HANDLE(currentThread()); }

    static QThread* currentThread();

   

protected:

    QThread(QThreadPrivate &dd, QObject *parent = 0);

 

private:

    explicit QThread(QObject *parent = 0);

    static QThread *instance;

 

    friend class QCoreApplication;

    friend class QThreadData;

    friend class QAdoptedThread;

    Q_DECLARE_PRIVATE(QThread)

};

该类的实现是全部交给了其内部类QThreadPrivate,接下来,我们分析QThreadPrivate类,该类在qthread_p.h中定义。

在该文件中,我们看到了:

class QAbstractEventDispatcher;

class QEventLoop;

这两个前向声明可以看出来,这里需要用到时间传递,下面就刚好定义了一些与事件相关的类:

class QPostEvent

{

public:

    QObject *receiver;

    QEvent *event;

    int priority;

    inline QPostEvent()

        : receiver(0), event(0), priority(0)

    { }

    inline QPostEvent(QObject *r, QEvent *e, int p)

        : receiver(r), event(e), priority(p)

    { }

};

inline bool operator<(int priority, const QPostEvent &pe)

{

    return pe.priority < priority;

}

inline bool operator<(const QPostEvent &pe, int priority)

{

    return priority < pe.priority;

}

该类保存了接收类的对象指针,发送的事件指针,以及优先级信息。重载的比较运算法,用于比较优先级高低。

class QPostEventList : public QList<QPostEvent>

{

public:

    // recursion == recursion count for sendPostedEvents()

    int recursion;

 

    // sendOffset == the current event to start sending

    int startOffset;

    // insertionOffset == set by sendPostedEvents to tell postEvent() where to start insertions

    int insertionOffset;

 

    QMutex mutex;

 

    inline QPostEventList()

        : QList<QPostEvent>(), recursion(0), startOffset(0), insertionOffset(0)

    { }

};

该类用于对QPostEvent列表的一个封装同时提供了多线程同步功能。

接下来是QThreadPrivate类的定义了:

class QThreadPrivate : public QObjectPrivate

{

    Q_DECLARE_PUBLIC(QThread)

 

public:

    QThreadPrivate(QThreadData *d = 0);

    ~QThreadPrivate();

 

    mutable QMutex mutex;

 

    bool running;

    bool finished;

    bool terminated;

 

    uint stackSize;

    QThread::Priority priority;

 

    static QThread *threadForId(int id);

 

#ifdef Q_OS_UNIX

    pthread_t thread_id;

    QWaitCondition thread_done;

 

    static void *start(void *arg);

#if defined(Q_OS_SYMBIAN)

    static void finish(void *arg, bool lockAnyway=true, bool closeNativeHandle=true);

#else

    static void finish(void *);

#endif

#endif // Q_OS_UNIX

 

#if defined(Q_OS_WIN32) || defined(Q_OS_WINCE)

    HANDLE handle;

    unsigned int id;

    int waiters;

 

    static unsigned int __stdcall start(void *);

    static void finish(void *, bool lockAnyway=true);

#endif // Q_OS_WIN32

 

#if defined(Q_OS_WIN32) || defined(Q_OS_WINCE) || defined (Q_OS_SYMBIAN)

    bool terminationEnabled, terminatePending;

# endif

    QThreadData *data;

 

    static void createEventDispatcher(QThreadData *data);

};

这里我们看到了创建事件分派器的代码:

void QThreadPrivate::createEventDispatcher(QThreadData *data)

{

#if !defined(QT_NO_GLIB)

    if (qgetenv("QT_NO_GLIB").isEmpty()

        && qgetenv("QT_NO_THREADED_GLIB").isEmpty()

        && QEventDispatcherGlib::versionSupported())

        data->eventDispatcher = new QEventDispatcherGlib;

    else

#endif

#ifdef Q_OS_SYMBIAN

        data->eventDispatcher = new QEventDispatcherSymbian;

#else

        data->eventDispatcher = new QEventDispatcherUNIX;

#endif

    data->eventDispatcher->startingUp();

}

但是这里居然没有关于Win32的类对象创建,看来需要继续寻找。

    bool running;

    bool finished;

    bool terminated;

    uint stackSize;

    QThread::Priority priority;

这里定义了类的运行状态,堆得大小,优先级信息。

现在找到了问题所在,为什么刚才在createEventDispatcher中没有找到Windows的事件派送器创建,我找错了文件,在qthread_win.cpp中,我们再去看下刚才的那个函数。

void QThreadPrivate::createEventDispatcher(QThreadData *data)

{

    data->eventDispatcher = new QEventDispatcherWin32;

    data->eventDispatcher->startingUp();

}

这里,我们找到了我们想要的东西。

下面,我们看下start函数:

unsigned int __stdcall QThreadPrivate::start(void *arg)

{

    QThread *thr = reinterpret_cast<QThread *>(arg);

    QThreadData *data = QThreadData::get2(thr);

 

    qt_create_tls();

    TlsSetValue(qt_current_thread_data_tls_index, data);

 

    QThread::setTerminationEnabled(false);

 

    data->quitNow = false;

    // ### TODO: allow the user to create a custom event dispatcher

    createEventDispatcher(data);

 

#if !defined(QT_NO_DEBUG) && defined(Q_CC_MSVC) && !defined(Q_OS_WINCE)

    // sets the name of the current thread.

    QByteArray objectName = thr->objectName().toLocal8Bit();

    qt_set_thread_name((HANDLE)-1,

                       objectName.isEmpty() ?

                       thr->metaObject()->className() : objectName.constData());

#endif

 

    emit thr->started();

    QThread::setTerminationEnabled(true);

    thr->run();

 

    finish(arg);

    return 0;

}

在该方法的实现中,我们看到了创建事件分配器的方法,在创建过程中,不允许程序外部中断运行过程。

接下来,我们看下QThread类的方法实现:

void QThread::start(Priority priority)

{

    Q_D(QThread);

    QMutexLocker locker(&d->mutex);

 

    if (d->running)

        return;

 

    d->running = true;

    d->finished = false;

    d->terminated = false;

 

    /*

      NOTE: we create the thread in the suspended state, set the

      priority and then resume the thread.

 

      since threads are created with normal priority by default, we

      could get into a case where a thread (with priority less than

      NormalPriority) tries to create a new thread (also with priority

      less than NormalPriority), but the newly created thread preempts

      its 'parent' and runs at normal priority.

    */

    d->handle = (Qt::HANDLE) _beginthreadex(NULL, d->stackSize, QThreadPrivate::start,

                                            this, CREATE_SUSPENDED, &(d->id));

 

    if (!d->handle) {

        qErrnoWarning(errno, "QThread::start: Failed to create thread");

        d->running = false;

        d->finished = true;

        return;

    }

 

    int prio;

    d->priority = priority;

    switch (d->priority) {

    case IdlePriority:

        prio = THREAD_PRIORITY_IDLE;

        break;

 

    case LowestPriority:

        prio = THREAD_PRIORITY_LOWEST;

        break;

 

    case LowPriority:

        prio = THREAD_PRIORITY_BELOW_NORMAL;

        break;

 

    case NormalPriority:

        prio = THREAD_PRIORITY_NORMAL;

        break;

 

    case HighPriority:

        prio = THREAD_PRIORITY_ABOVE_NORMAL;

        break;

 

    case HighestPriority:

        prio = THREAD_PRIORITY_HIGHEST;

        break;

 

    case TimeCriticalPriority:

        prio = THREAD_PRIORITY_TIME_CRITICAL;

        break;

 

    case InheritPriority:

    default:

        prio = GetThreadPriority(GetCurrentThread());

        break;

    }

 

    if (!SetThreadPriority(d->handle, prio)) {

        qErrnoWarning("QThread::start: Failed to set thread priority");

    }

 

    if (ResumeThread(d->handle) == (DWORD) -1) {

        qErrnoWarning("QThread::start: Failed to resume new thread");

    }

}

通过该方法中的说明,我们了解到,当线程创建时,其默认权限为normal。通过_beginthreadex方法创建线程。线程创建后首先被挂起,当完成优先级的设定后,会唤醒线程。

相应的,其他几个线程的方法也是类似的操作。但是今天要休息了,只能在明天继续分析。明天再次查看QCoreAppcation类的exec()方法,看是怎么启动线程的。

 

20091031日星期六 2233

 

你可能感兴趣的:(thread,多线程,Class,qt,WinCE,recursion)