2016-07-10 19 views
0

Ich habe einen Bool-Wert, der ständig streamt. Ich muss eine Funktion auslösen, wenn die Bool wahr wird, und eine andere, wenn die Bool falsch wird, aber nur einmal pro Änderung, so dass ich eine while(true) Schleife nicht verwenden kann.C++ Trigger-Funktion, wenn Bool ändert

Was ist der beste Weg in C++, einen Wert "zu beobachten" und auszulösen, wenn er sich ändert?

Vielen Dank.

+0

Lookup für [ 'std :: condition_variable'] (http://en.cppreference.com/w/cpp/thread/condition_variable) –

Antwort

1

Ich würde gehen, indem Sie eine FlagTrue-Variable und eine Variable FlagFalse setzen. Wenn Sie das erste True treffen, ändert sich flagTrue von false in true und alle folgenden True booleans werden ignoriert. In ähnlicher Weise würde flagFalse von False auf True wechseln und alle folgenden False-Booleans ignorieren, wenn Sie auf Ihren Burst False treffen. Wenn der geprüfte Boolesche Wert von "Wahr" zu "Falsch" wechselt, ändern Sie "FlagTrue" ebenfalls in "False" und im anderen Fall in "false".
Beispiel:

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

Vielen Dank! (Bearbeitet) Also das Gegenteil wäre: 'if (bool == false && flagFalse == False) { // DoSomething flagTrue = False; flagFalse = Wahr; } ' Ist das richtig? – anti

+1

Ich habe die Initialisierung hinzugefügt. Ich glaube, sie machen das klarer. Ja, die Converse, die Sie hinzugefügt haben, ist korrekt. Ich habe meinen Code aktualisiert. Bitte schau es dir an. –

+0

ah ich sehe. Macht perfekt Sinn. Danke nochmal! – anti

0

einen Blick auf dem Observer-Muster nehmen. Sie könnten Ihren Booleschen Wert in eine Hilfsklasse einfügen, die jedes Mal, wenn der Boolesche Wert gesetzt wird, ein Ereignis auslöst.

Beispiel Implementierung eines beobachtbaren Bool:

#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(); 
     } 
    } 
}; 

Dies kann eine Menge verbessert werden. Ein wirklich netter Weg wäre es, implizite Konvertierung von und nach bool zu implementieren (Aber Vorsicht, das Überladen des '=' Operators für bool könnte gefährlich sein). Sie könnten es zur Unterstützung beliebiger Typen anstelle von bool simulieren, Sie sollten einen intelligenten Zeiger anstelle von rohen Zeigern verwenden (std::weak_ptr wäre am besten) und statt einer Observer-Klasse sollten Sie wahrscheinlich Funktionszeiger verwenden, um lambdas richtig zu unterstützen. Wenn Sie es richtig machen, können Sie die Klasse wie einen normalen booleschen Wert verwenden, mit einem kleinen Overhead, wenn ein neuer Wert gesetzt wird. Und standardmäßig werden alle Reaktionen auf eine Änderung von dem Thread ausgeführt, der den Wert geändert hat.

1

würde ich wahrscheinlich mit so etwas wie dies starten:

#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(); 

}