Skip to content

Implementation of a generic CallBackList #5710

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 10 commits into from
Nov 5, 2019
84 changes: 84 additions & 0 deletions cores/esp8266/CallBackList.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
#ifndef __CALLBACKLIST_H__
#define __CALLBACKLIST_H__


/*
CallBackList, An implemention for handling callback execution

Copyright (c) 2019 Herman Reintke. All rights reserved.
This file is part of the esp8266 core for Arduino environment.

This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.

This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/

#include <Arduino.h>
#include <memory>
#include <list>
#include <utility>

namespace experimental
{
namespace CBListImplentation
{

template<class cbFunctionT>
class CallBackList
{
public:
CallBackList (){};

struct CallBackInfo
{
CallBackInfo(cbFunctionT f) : cbFunction(f, true){};
CallBackInfo(cbFunctionT f, bool ar) : cbFunction(f), _allowRemove(ar) {};
cbFunctionT cbFunction;
bool _allowRemove = true;
bool allowRemove()
{
return _allowRemove;
}
};
using CallBackHandler = std::shared_ptr<CallBackInfo> ;
std::list<CallBackHandler> callBackEventList;

CallBackHandler add(cbFunctionT af, bool ad = true) {
CallBackHandler handler = std::make_shared<CallBackInfo>(CallBackInfo(af,ad));
callBackEventList.emplace_back(handler);
return handler;
}

void remove(CallBackHandler& dh) {
callBackEventList.remove(dh);
}

template<typename... Args>
void execute(Args... params) {
for(auto it = std::begin(callBackEventList); it != std::end(callBackEventList); ) {
CallBackHandler &handler = *it;
if (handler->allowRemove() && handler.unique()) {
it = callBackEventList.erase(it);
}
else {
handler->cbFunction(params...);
++it;
}
}
}
};

} //CBListImplementation
}//experimental

#endif // __CALLBACKLIST_H__
64 changes: 64 additions & 0 deletions libraries/esp8266/examples/CallBackList/CallBackGeneric.ino
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
#include <Arduino.h>
#include <Ticker.h>
#include "CallBackList.h"

using namespace experimental::CBListImplentation;

class exampleClass {
public:
exampleClass() {};

using exCallBack = std::function<void(int)>;
using exHandler = CallBackList<exCallBack>::CallBackHandler;

CallBackList<exCallBack> myHandlers;

exHandler setHandler(exCallBack cb) {
return myHandlers.add(cb);
}

void removeHandler(exHandler hnd) {
myHandlers.remove(hnd);
}

void trigger(int t) {
myHandlers.execute(t);
}
};

exampleClass myExample;

void cb1(int in) {
Serial.printf("Callback 1, in = %d\n", in);
}

void cb2(int in) {
Serial.printf("Callback 2, in = %d\n", in);
}

void cb3(int in, int s) {
Serial.printf("Callback 3, in = %d, s = %d\n", in, s);
}

Ticker tk, tk2, tk3;
exampleClass::exHandler e1 = myExample.setHandler(cb1);
exampleClass::exHandler e2 = myExample.setHandler(cb2);
exampleClass::exHandler e3 = myExample.setHandler(std::bind(cb3, std::placeholders::_1, 10));

void setup() {
Serial.begin(115200);

tk.attach_ms(2000, []() {
Serial.printf("trigger %d\n", (uint32_t)millis());
myExample.trigger(millis());
});
tk2.once_ms(10000, []() {
myExample.removeHandler(e2);
});
tk3.once_ms(20000, []() {
e3.reset();
});
}

void loop() {
}