QThread
中的 start()
方法底层实现源码涉及到一些跨平台的底层细节和系统调用,下面是一个简化版的源码分析。
void QThread::start()
{
Q_D(QThread); // 在这里创建 QThreadPrivate 对象
// 避免重复启动线程
if (d->isRunning) {
qWarning() << "QThread: Already running";
return;
}
d->isRunning = true;
// 创建并启动底层线程
int ret = pthread_create(&d->threadId, &d->attr, thread_start, this);
if (ret != 0) {
d->setError(QThreadPrivate::CreateThreadError, ret);
return;
}
// 等待底层线程启动
QMutexLocker locker(&d->mutex);
if (!d->threadData->startupSemaphore.tryAcquire(1, d->style == QThread::IdlePriority ? 5000 : ULONG_MAX)) {
qWarning("QThread::start(): Thread creation error: %s", strerror(d->error));
d->setError(QThreadPrivate::CreateThreadError, d->error);
return;
}
// 设置 thread id, isfinished 和 ispaused 属性
d->assignNativeThreadId(d->threadId);
d->isFinished = false;
d->isPaused = false;
// 发射 started 信号
emit started();
}
其中,thread_start
涉及到线程的底层创建和启动,我们只需要关注 start
函数中其他部分的实现。
QThreadPrivate
类定义了 QThread
类的私有数据(private data)成员,存储了线程的 ID、运行状态和错误码等信息。
在 start
函数中,首先通过 QThreadPrivate
的 isRunning
成员变量避免了重复启动线程。然后调用 pthread_create
函数创建并启动底层线程,如果返回值不为 0,则设置错误码并退出。在 pthread_create
函数内部,会调用 thread_start
来真正执行线程的入口点函数,并将 this
指针传递给该函数。
接着调用 tryAcquire
函数来等待底层线程启动。在 tryAcquire
函数中,等待 startupSemaphore
,该信号量会在底层线程内部启动完成后释放锁定,这时 tryAcquire
函数返回 true,控制流程返回到 start
函数中。如果 tryAcquire
函数在超时时间内未能获取到信号量,则设置错误码并退出。
在完成了一些底层细节的操作之后,start
函数将调用 emit started()
信号发射器来发送 started
信号。
需要注意的是,这里的底层实现源码仅仅是核心代码的简化并省略了很多细节,实际的底层实现涉及到了系统相关的调用和底层实现的细节。