move bluetooth code into something that is architecture specific...

because the ESP32 implementation will be different from NRF52
to make this possible I needed to decouple knowlege about bluetooth from
our mesh service.  Instead mesh service now uses the Obserable pattern
to let any interested consumer get notified of important mesh changes
(currently that is only bluetooth, but really we should do the same
thing for decoupling the GUI 'app' from the mesh service)

@girtsf would you mind reviewing my Observer changes? I haven't written
C++ code in a long time ;-)
This commit is contained in:
geeksville
2020-04-10 12:18:48 -07:00
parent 93a06906cb
commit 6ad451eb5f
13 changed files with 104 additions and 108 deletions

View File

@@ -4,38 +4,83 @@
#include <list>
class Observable;
template <class T> class Observable;
class Observer
/**
* An observer which can be mixed in as a baseclass. Implement onNotify as a method in your class.
*/
template <class T> class Observer
{
Observable *observed;
Observable<T> *observed;
public:
Observer() : observed(NULL) {}
virtual ~Observer();
void observe(Observable *o);
void observe(Observable<T> *o);
private:
friend class Observable;
friend class Observable<T>;
virtual void onNotify(Observable *o) = 0;
protected:
virtual void onNotify(T arg) = 0;
};
class Observable
/**
* An observer that calls an arbitrary method
*/
template <class Callback, class T> class CallbackObserver : public Observer<T>
{
std::list<Observer *> observers;
typedef void (Callback::*ObserverCallback)(T arg);
Callback *objPtr;
ObserverCallback method;
public:
void notifyObservers()
CallbackObserver(Callback *_objPtr, ObserverCallback _method) : objPtr(_objPtr), method(_method) {}
protected:
virtual void onNotify(T arg) { (objPtr->*method)(arg); }
};
/**
* An observable class that will notify observers anytime notifyObservers is called. Argument type T can be any type, but for
* performance reasons a pointer or word sized object is recommended.
*/
template <class T> class Observable
{
std::list<Observer<T> *> observers;
public:
/**
* Tell all observers about a change, observers can process arg as they wish
*/
void notifyObservers(T arg)
{
for (std::list<Observer *>::const_iterator iterator = observers.begin(); iterator != observers.end(); ++iterator) {
(*iterator)->onNotify(this);
for (typename std::list<Observer<T> *>::const_iterator iterator = observers.begin(); iterator != observers.end();
++iterator) {
(*iterator)->onNotify(arg);
}
}
void addObserver(Observer *o) { observers.push_back(o); }
private:
friend class Observer<T>;
void removeObserver(Observer *o) { observers.remove(o); }
// Not called directly, instead call observer.observe
void addObserver(Observer<T> *o) { observers.push_back(o); }
void removeObserver(Observer<T> *o) { observers.remove(o); }
};
template <class T> Observer<T>::~Observer()
{
if (observed)
observed->removeObserver(this);
observed = NULL;
}
template <class T> void Observer<T>::observe(Observable<T> *o)
{
o->addObserver(this);
}