qt源码地址:
Qt的线程应该是大家讨论比较多的,也是迷惑比较多的。这主要和qt线程实现机制和上层封装出的接口有关,封装的不清不楚,接口要么就封装的完全不知道里面是什么东西,要么就让大家知道里面是什么,(当然前者是最正确的)新人经常犯的错误是继承了线程类意味从此这个类里面的所有东西都是线程的,单是实际上只有run方法是线程里面运行。当然还有那个movetothread,暂且我们不论。
好了回到正题贴代码:
当我们继承qt线程创建线程的时候,实际上只有到了运行start的时候才创建了线程。下面是qt源码的start
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;
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
d->priority = priority;
switch (priority) {
"qt 线程权限设置,qt针对各个平台,封装出了自己的设置"
case InheritPriority:
{
pthread_attr_setinheritsched(&attr, PTHREAD_INHERIT_SCHED);
break;
}
default:
{
int sched_policy;
if (pthread_attr_getschedpolicy(&attr, &sched_policy) != 0) {
// failed to get the scheduling policy, don't bother
// setting the priority
qWarning("QThread::start: Cannot determine default scheduler policy");
break;
}
int prio_min = sched_get_priority_min(sched_policy);
int prio_max = sched_get_priority_max(sched_policy);
if (prio_min == -1 || prio_max == -1) {
// failed to get the scheduling parameters, don't
// bother setting the priority
qWarning("QThread::start: Cannot determine scheduler priority range");
break;
}
int prio;
switch (priority) {
case IdlePriority:
prio = prio_min;
break;
case TimeCriticalPriority:
prio = prio_max;
break;
default:
// crudely scale our priority enum values to the prio_min/prio_max
prio = (priority * (prio_max - prio_min) / TimeCriticalPriority) + prio_min;
prio = qMax(prio_min, qMin(prio_max, prio));
break;
}
sched_param sp;
sp.sched_priority = prio;
if (pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED) != 0
|| pthread_attr_setschedpolicy(&attr, sched_policy) != 0
|| pthread_attr_setschedparam(&attr, &sp) != 0) {
// could not set scheduling hints, fallback to inheriting them
pthread_attr_setinheritsched(&attr, PTHREAD_INHERIT_SCHED);
}
break;
}
}
#endif // _POSIX_THREAD_PRIORITY_SCHEDULING
if (d->stackSize > 0) {
#if defined(_POSIX_THREAD_ATTR_STACKSIZE) && (_POSIX_THREAD_ATTR_STACKSIZE-0 > 0)
int code = pthread_attr_setstacksize(&attr, d->stackSize);
#else
int code = ENOSYS; // stack size not supported, automatically fail
#endif // _POSIX_THREAD_ATTR_STACKSIZE
if (code) {
qWarning("QThread::start: Thread stack size error: %s",
qPrintable(qt_error_string(code)));
// we failed to set the stacksize, and as the documentation states,
// the thread will fail to run...
d->running = false;
d->finished = false;
return;
}
}
"
真正创建线程,线程实体函数是 QThreadPrivate::start
"
int code =
pthread_create(&d->thread_id, &attr, QThreadPrivate::start, this);
if (code == EPERM) {
// caller does not have permission to set the scheduling
// parameters/policy
code =
pthread_create(&d->thread_id, &attr, QThreadPrivate::start, this);
}
pthread_attr_destroy(&attr);
if (code) {
qWarning("QThread::start: Thread creation error: %s", qPrintable(qt_error_string(code)));
d->running = false;
d->finished = false;
d->thread_id = 0;
#ifdef Q_OS_SYMBIAN
d->data->symbian_thread_handle.Close();
#endif
}
}
我们接着分析:
线程的实体函数,在线程实体里面调用了run。
void *QThreadPrivate::start(void *arg)
{
QThread *thr = reinterpret_cast<QThread *>(arg);
QThreadData *data = QThreadData::get2(thr);
pthread_once(¤t_thread_data_once, create_current_thread_data_key);
pthread_setspecific(current_thread_data_key, data);
data->ref();
data->quitNow = false;
// ### TODO: allow the user to create a custom event dispatcher
createEventDispatcher(data);
emit thr->started();
"
线程里面运行了run函数,run函数熟悉不,其实就是我们继承的线程类里面run的虚函数
归根到底,就是创建的线程里面回调了run,也就是我们自己的函数,所以说qt只有run
是在线程里面。
"
thr->run();
return 0;
}