2017-05-08 64 views
0

我目前正在考慮QTimer實現的線程安全性。QTimer線程安全的方法'isActive()'?

在我的應用程序中,我使用bool isActive()方法來檢查計時器是否正在運行。正如我打算從其他線程使用這種方法,我的想法轉到線程安全考慮。

根據我的研究,方法bool isActive()不是線程安全的。

這裏是我的假設:

QTimerQTimer source code)的實施表明,bool isActive()只是檢查,如果該成員變量int id;大於0:

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

這個成員變量在初始化構造函數與INV_TIMER這是一個定義爲-1。當定時器啓動時,它將被設置爲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); 
} 

當在QTimer::start()從另一個線程執行isActive()一個電話,在我看來bool isActive()返回值可能是無效的。

我希望能夠驗證我的假設的人的意見。

爲了達到線程安全性,我只是用互斥體將我的調用包裝到定時器中,就像下面顯示的代碼片段一樣。

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; 

}; 
+1

QTimer不是線程安全的,甚至不可重入。因此,即使代碼中的互斥體也不會使其安全。 – peppe

回答

1

如果你想呼叫QTimer::isActive從另一個線程,那麼你的解決方案看起來是安全的。 isActive只訪問id成員變量,因此您需要互斥 - 保護所有寫入id以及從線程讀取id。你做了isActivestop,這樣看起來不錯。

請注意,如果您曾經調用QTimer的其他方法寫入id,您將會遇到未定義的行爲。所以請小心不要撥打QTimer::setInterval(),QTimer::~QTimer()(!)等。也請不要使用單發定時器,因爲這會寫入idQTimer::timerEvent()

一般來說,包裝一個已經存在的類並添加互斥體是很危險的,不管這個工作是否依賴於所述類的內部,而且這些都很難檢查所有的情況。此外,內部版本可能會在下一個Qt版本中發生變化,也許在下一個版本中QTimer::timerEvent()將無條件地更改id,並且您的解決方案不再是線程安全的。

所以,雖然你的方法的工作,一般來說,我會建議反對它。