123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990 | // Copyright (C) 2022 The Qt Company Ltd.// Copyright (C) 2016 Intel Corporation.// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only#include <QtCore/private/qsingleshottimer_p.h>#include"qcoreapplication.h"#include"qmetaobject_p.h"#include"private/qnumeric_p.h"#include"qthread.h" QT_BEGIN_NAMESPACE QSingleShotTimer::QSingleShotTimer(Duration interval,Qt::TimerType timerType,const QObject *r,const char*member):QObject(QAbstractEventDispatcher::instance()){connect(this,SIGNAL(timeout()), r, member);startTimerForReceiver(interval, timerType, r);}QSingleShotTimer::QSingleShotTimer(Duration interval,Qt::TimerType timerType,const QObject *r,QtPrivate::QSlotObjectBase *slotObj):QObject(QAbstractEventDispatcher::instance()){int signal_index =QMetaObjectPrivate::signalOffset(&staticMetaObject);Q_ASSERT(QMetaObjectPrivate::signal(&staticMetaObject, signal_index).name() =="timeout");QObjectPrivate::connectImpl(this, signal_index, r ? r :this,nullptr, slotObj,Qt::AutoConnection,nullptr, &staticMetaObject);startTimerForReceiver(interval, timerType, r);}QSingleShotTimer::~QSingleShotTimer() =default;/* Move the timer, and the dispatching and handling of the timer event, into the same thread as where it will be handled, so that it fires reliably even if the thread that set up the timer is busy.*/voidQSingleShotTimer::startTimerForReceiver(Duration interval,Qt::TimerType timerType,const QObject *receiver){if(receiver && receiver->thread() !=thread()) { QObjectPrivate *d_ptr =QObjectPrivate::get(this); d_ptr->sendChildEvents =false;setParent(nullptr);moveToThread(receiver->thread());QCoreApplication::postEvent(this,newStartTimerEvent(this,QDeadlineTimer(interval, timerType)));// the event owns "this" and is handled concurrently, so unsafe to// access "this" beyond this point}else{ timer.start(interval, timerType,this);}}voidQSingleShotTimer::timerFinished(){ Q_EMIT timeout();delete this;}voidQSingleShotTimer::timerEvent(QTimerEvent *event){if(event->id() ==Qt::TimerId::Invalid) { StartTimerEvent *startTimerEvent =static_cast<StartTimerEvent *>(event);Q_UNUSED(startTimerEvent->timer.release());// it's the same as "this"const QDeadlineTimer &deadline = startTimerEvent->deadline;if(deadline.hasExpired()) {timerFinished();}else{ timer.start(deadline.remainingTimeAsDuration(), deadline.timerType(),this);// we are now definitely in a thread that has an event dispatchersetParent(QThread::currentThread()->eventDispatcher());}}else{// need to kill the timer _before_ we emit timeout() in case the// slot connected to timeout calls processEvents() timer.stop();timerFinished();}} QT_END_NAMESPACE #include"moc_qsingleshottimer_p.cpp"
|