简体   繁体   English

QTimer的方法'isActive()'是线程安全的吗?

[英]Is the method 'isActive()' of QTimer threadsafe?

I'm currently thinking about the threadsafety of the QTimer implementation. 我目前正在考虑QTimer实现的线程安全性。

In my application I use the bool isActive() method to check if a timer is running or not. 在我的应用程序中,我使用bool isActive()方法检查计时器是否正在运行。 As I plan to use this method also from other threads, my thoughts went over to threadsafety considerations. 当我计划在其他线程中也使用此方法时,我的想法就涉及线程安全性考虑因素。

According to my research the method bool isActive() is not threadsafe. 根据我的研究, bool isActive()方法不是线程安全的。

Here are my assumptions: 这是我的假设:

The implementation of QTimer ( QTimer source code ) shows that bool isActive() just checks if the member-variable int id; QTimer的实现( QTimer源代码 )显示, bool isActive()仅检查成员变量int id; is greater than 0: 大于0:

inline bool isActive() const { return id >= 0; }

This member variable is initialized at the constructor with INV_TIMER which is a define to -1 . 此成员变量在构造函数中使用INV_TIMER初始化, INV_TIMER-1的定义。 When the timer is started, it will be set to the return-value of the int QObject::startTimer(int interval) . 当计时器启动时,它将被设置为int QObject::startTimer(int interval)的返回值。

/*! \overload start()
    Starts or restarts the timer with the timeout specified in \l interval.
    If \l singleShot is true, the timer will be activated only once.
*/
void QTimer::start()
{
    if (id != INV_TIMER)                        // stop running timer
        stop();
    nulltimer = (!inter && single);
    id = QObject::startTimer(inter);
}

When a call to isActive() is executed during QTimer::start() from another thread, in my opinion the returned value of bool isActive() could be invalid. 当我从另一个线程在QTimer::start()期间执行对isActive()的调用时,我认为bool isActive()的返回值可能无效。

I would appreciate the opinion of someone who is able to verify my assumptions. 我会感谢能够验证我的假设的人的意见。

To reach thread safety, I would just wrap my call to the timer with a mutex, like in the code snippet shown below. 为了达到线程安全,我只需使用互斥体将对计时器的调用包装起来,如下面的代码片段所示。

class SensorControl : public QObject
{
    Q_OBJECT

public:
    SensorControl();    // inits and interval-settings are done at implementation

    bool Start()
    {
        QMutexLocker lock(&m_mutexTimer);
        return m_pTimer->start();
    }

    void Stop()
    {
        QMutexLocker lock(&m_mutexTimer);
        return m_pTimer->stop();
    }

    bool IsMeasuring() const
    {
        QMutexLocker lock(&m_mutexTimer);
        return m_pTimer->isActive();
    }

private:

    QMutex m_mutexTimer;
    QTimer* m_pTimer;

};

If you want to only call QTimer::isActive from another thread, then your solution looks safe. 如果你想调用QTimer::isActive从另一个线程,那么你的解决方案看起来是安全的。 isActive only accesses the id member variable, so you need to mutex-protect all writes to id , and the read of id from your thread. isActive只访问id成员变量,因此您需要互斥保护所有对id写入以及从线程中读取id You did that for isActive and stop , so that looks good. 您是为isActivestop这样做的,所以看起来不错。

Note that if you ever call other methods of QTimer that write to id , you will get undefined behaviour. 请注意,如果您曾经调用其他写入idQTimer方法,则将获得未定义的行为。 So take care to not call things like QTimer::setInterval() , QTimer::~QTimer() (!) and so on. 因此,请注意不要调用诸如QTimer::setInterval()QTimer::~QTimer() (!)之类的东西。 Also don't use a singleshot timer, as that will write to id in QTimer::timerEvent() . 也不要使用Singleshot计时器,因为它将写入QTimer::timerEvent() id

In general wrapping an existing class and adding mutexes is dangerous, whether that works depends on the internals of said class, and those are hard to check for all cases. 通常,包装一个现有的类并添加互斥体是危险的,这是否起作用取决于该类的内部,并且很难在所有情况下进行检查。 Also, internals might change in the next Qt version, maybe in the next version QTimer::timerEvent() will unconditionally change the id , and your solution is not thread safe anymore. 同样,内部结构可能在下一个Qt版本中发生变化,也许在下一个版本中QTimer::timerEvent()将无条件地更改id ,并且您的解决方案不再是线程安全的。

So while your approach works, in general I would recommend against it. 因此,尽管您的方法可行,但总体上我还是建议不要这样做。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM