2016-07-10 118 views
0

我有一個不斷流的bool值。當布爾變爲true時,我需要觸發一個函數,另一個布爾變爲false時,但每次更改只有一次,所以我不能使用while(true)循環。bool更改時的C++觸發函數

什麼是最好的方式在c + +「觀察」一個值,並在它發生變化時觸發?

謝謝。

+0

查找爲['的std :: condition_variable'(http://en.cppreference.com/w/cpp/thread/condition_variable) –

回答

1

我會去設置一個flagTrue變量和一個flagFalse變量。當您遇到第一個True時,flagTrue從false更改爲true,並且所有跟隨True的布爾值都將被忽略。同樣,當你遇到你的錯誤False時,flagFalse會從False變爲True,並忽略所有跟隨的False布爾值。另外,當被檢查的布爾值從True更改爲False時,將會將flagTrue更改爲False,並且在另一種情況下也會類似。
例子:

flagTrue = false 
flagFalse = false 
if (bool == true && flagTrue == false) 
{ 
    // DoSomething 
    flagTrue = true; 
    flagFalse = false; 
} 
else if (bool == false && flagFalse == false) 
{ 
    // DoSomething 
    flagTrue = false; 
    flagFalse = true; 
} 
+0

謝謝! (編輯)所以相反會是: 'if(bool == false && flagFalse == False) { // DoSomething flagTrue = False; flagFalse = True; }' 是嗎? – anti

+1

我已經添加了初始化。我相信他們更清楚。是的,你添加的話是正確的。我更新了我的代碼。請檢查一下。 –

+0

啊我明白了。非常有意義。再次感謝你! – anti

0

看看Observer模式。你可以將你的布爾值封裝在一個助手類中,當布爾值被設置時觸發一個事件。

實施例實現可觀察到的布爾的:

#include <vector> 

class Observer { 
public: 
    virtual void valueChanged() = 0; 
}; 

class ObservableBool { 
private: 
    bool value; 
    std::vector<Observer*> observers = std::vector<Observer*>(); 

public: 
    bool getValue() { 
     return value; 
    } 

    bool setValue(bool value) { 
     bool changed = (value != this->value); 
     this->value = value; 
     if(changed) raiseEvent(); 
    } 

    void addObserver(Observer* observer) { 
     observers.push_back(observer); 
    } 

    void removeObserver(Observer* observer) { 
     observers.erase(std::find(observers.begin, observers.end, observer)); 
    } 

private: 
    void raiseEvent() { 
     for (int i = 0; i < observers.size; ++i) { 
      observers[i]->valueChanged(); 
     } 
    } 
}; 

這可以提高了很多。一個非常好的方法是實現從bool到bool的隱式轉換(但要小心,爲bool設置'='運算符會很危險)。你可以模板它來支持任意類型,而不僅僅是布爾,你應該使用智能指針而不是原始指針(std::weak_ptr將是最好的),而不是Observer類,你應該使用函數指針來正確支持lambdas。如果你做得對,你可以像普通的布爾值一樣使用這個類,當設置一個新的值時,會有小的開銷。默認情況下,所有對更改的反應都是由更改值的線程執行的。

1

我可能會開始像這樣:

#include <functional> 
#include <atomic> 
#include <iostream> 

struct trigger 
{ 
    using closure_type = std::function<void()>; 

    trigger(closure_type on_set, closure_type on_reset, bool initial_state = false) 
    : _state { initial_state } 
    , _on_set(std::move(on_set)) 
    , _on_reset(std::move(on_reset)) 
    {} 

    void set() { 
    if (not _state.exchange(true)) { 
     _on_set(); 
    } 
    } 

    void reset() { 
    if (_state.exchange(false)) { 
     _on_reset(); 
    } 
    } 

    std::atomic<bool> _state; 
    std::function<void()> _on_set; 
    std::function<void()> _on_reset; 
}; 

void has_set() { 
    // you can marshall accross threads here by posting calls to a 
    // queue 
    std::cout << __func__ << std::endl; 
} 

void has_unset() { 
    // you can marshall accross threads here by posting calls to a 
    // queue 
    std::cout << __func__ << std::endl; 
} 

int main() 
{ 
    trigger t { has_set, has_unset }; 

    t.set(); 
    t.set(); 

    t.reset(); 
    t.reset(); 

} 
相關問題