Skip to content
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

Make sample show more examples of std::function and std::bind #1378

Merged
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 32 additions & 0 deletions Sming/SmingCore/Timer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,20 @@ Timer& Timer::initializeUs(uint32_t microseconds, TimerDelegate delegateFunction
return *this;
}

Timer& Timer::initializeMs(uint32_t milliseconds, TimerDelegateStdFunction delegateFunction)
{
setCallback(delegateFunction);
setIntervalMs(milliseconds);
return *this;
}

Timer& Timer::initializeUs(uint32_t microseconds, TimerDelegateStdFunction delegateFunction)
{
setCallback(delegateFunction);
setIntervalUs(microseconds);
return *this;
}

void Timer::start(bool repeating/* = true*/)
{
this->repeating = repeating;
Expand Down Expand Up @@ -135,6 +149,7 @@ void Timer::setCallback(InterruptCallback interrupt/* = NULL*/)
ETS_INTR_LOCK();
callback = interrupt;
delegate_func = nullptr;
delegate_stdfunc = nullptr;
ETS_INTR_UNLOCK();

if (!interrupt)
Expand All @@ -146,6 +161,19 @@ void Timer::setCallback(TimerDelegate delegateFunction)
ETS_INTR_LOCK();
callback = nullptr;
delegate_func = delegateFunction;
delegate_stdfunc = nullptr;
ETS_INTR_UNLOCK();

if (!delegateFunction)
stop();
}

void Timer::setCallback(const TimerDelegateStdFunction& delegateFunction)
{
ETS_INTR_LOCK();
callback = nullptr;
delegate_func = nullptr;
delegate_stdfunc = delegateFunction;
ETS_INTR_UNLOCK();

if (!delegateFunction)
Expand Down Expand Up @@ -197,6 +225,10 @@ void Timer::tick()
{
delegate_func();
}
else if (delegate_stdfunc)
{
delegate_stdfunc();
}
else{
stop();
}
Expand Down
34 changes: 28 additions & 6 deletions Sming/SmingCore/Timer.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
#ifndef _SMING_CORE_Timer_H_
#define _SMING_CORE_Timer_H_


#include <functional>
#include "../SmingCore/Interrupts.h"
#include "../SmingCore/Delegate.h"
#include "../Wiring/WiringFrameworkDependencies.h"
Expand All @@ -25,6 +25,7 @@
#define MAX_OS_TIMER_INTERVAL_US 268435000

typedef Delegate<void()> TimerDelegate;
typedef std::function<void()> TimerDelegateStdFunction;

class Timer
{
Expand Down Expand Up @@ -59,16 +60,31 @@ class Timer
* @param milliseconds Duration of timer in milliseconds
* @param delegateFunction Function to call when timer triggers
* @note Delegate callback method
* @deprecated Use initializeMs(xx, TimerDelegateStdFunction); instead.
*/
Timer& IRAM_ATTR initializeMs(uint32_t milliseconds, TimerDelegate delegateFunction = NULL); // Init in Milliseconds.

/** @brief Initialise microsecond timer
* @param microseconds Duration of timer in milliseconds
* @param delegateFunction Function to call when timer triggers
* @note Delegate callback method
* @deprecated Use initializeMs(xx, TimerDelegateStdFunction); instead.
*/
Timer& IRAM_ATTR initializeUs(uint32_t microseconds, TimerDelegate delegateFunction = NULL); // Init in Microseconds.

/** @brief Initialise millisecond timer
* @param milliseconds Duration of timer in milliseconds
* @param delegateFunction Function to call when timer triggers
* @note Delegate callback method
*/
Timer& IRAM_ATTR initializeMs(uint32_t milliseconds, TimerDelegateStdFunction delegateFunction = nullptr); // Init in Milliseconds.

/** @brief Initialise microsecond timer
* @param microseconds Duration of timer in milliseconds
* @param delegateFunction Function to call when timer triggers
* @note Delegate callback method
*/
Timer& IRAM_ATTR initializeUs(uint32_t microseconds, TimerDelegateStdFunction delegateFunction = nullptr); // Init in Microseconds.
/** @brief Start timer running
* @param repeating Set to true for repeating timer. Set to false for one-shot.
*/
Expand Down Expand Up @@ -120,11 +136,16 @@ class Timer
*/
void IRAM_ATTR setCallback(InterruptCallback interrupt = NULL);

/** @brief Set timer trigger function
* @param delegateFunction Function to be called on timer trigger
* @note Delegate callback method
*/
void IRAM_ATTR setCallback(TimerDelegate delegateFunction);
/** @brief Set timer trigger function
* @param delegateFunction Function to be called on timer trigger
* @note Delegate callback method
*/
void IRAM_ATTR setCallback(TimerDelegate delegateFunction);
/** @brief Set timer trigger function
* @param delegateFunction Function to be called on timer trigger
* @note Delegate callback method
*/
void IRAM_ATTR setCallback(const TimerDelegateStdFunction& delegateFunction);


protected:
Expand All @@ -142,6 +163,7 @@ class Timer
uint64_t interval = 0;
InterruptCallback callback = nullptr;
TimerDelegate delegate_func = nullptr;
TimerDelegateStdFunction delegate_stdfunc = nullptr;
bool repeating = false;
bool started = false;

Expand Down
138 changes: 109 additions & 29 deletions samples/Basic_Delegates/app/application.cpp
Original file line number Diff line number Diff line change
@@ -1,45 +1,125 @@
#include <user_config.h>
#include <SmingCore.h>

class LedBlinker
void plainOldOrdinaryFunction()
{
debugf("plainOldOrdinaryFunction");
}


void functionWithMoreComlicatedSignature(int a, String b)
{
debugf("functionWithMoreComlicatedSignature %d %s", a, b.c_str());
}

public :
LedBlinker(int reqPin) : ledPin(reqPin) {
pinMode(ledPin, OUTPUT);
};

class Task
{

public:
Task() {};
bool setTimer(int reqInterval) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Coding-Style: Put the opening curly brace on the next line.

if (reqInterval <= 0) return false;
ledInterval = reqInterval;
if (reqInterval <= 0) {
return false;
}
taskInterval = reqInterval;
return true;
}
void blink(bool reqRun) {
if (reqRun) {
ledTimer.initializeMs(ledInterval, TimerDelegate(&LedBlinker::ledBlink,this)).start();
}
else {
ledTimer.stop();
}

// This example show the way delegates have been used in Sming in the past.
void blinkOldDelegate() {
taskTimer.initializeMs(taskInterval, TimerDelegate(&Task::doOldDelegate, this)).start();
}
void ledBlink () { ledState = !ledState ; digitalWrite(ledPin, ledState);}

private :
int ledPin = 2;
Timer ledTimer;
int ledInterval = 1000;
bool ledState = true;
};
// This example shows how to use a plain old ordinary function as a callback
void callPlainOldOrdinaryFunction() {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Coding-Style: Put the opening curly brace on the next line.

taskTimer.initializeMs(taskInterval, TimerDelegateStdFunction(plainOldOrdinaryFunction)).start();
// or just
// taskTimer.initializeMs(taskInterval, plainOldOrdinaryFunction).start();
}


// This example shows how to use std::bind to make us of a function that has more parameters than our signature has
void showHowToUseBind() {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Coding-Style: Put the opening curly brace on the next line.

auto b = std::bind(functionWithMoreComlicatedSignature, 2, "parameters");
taskTimer.initializeMs(taskInterval, b).start();
}

// Sming now allows the use of std::function
// This example shows how to use a lamda expression as a callback
void callLamda() {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Coding-Style: Put the opening curly brace on the next line.

int foo = 123;
taskTimer.initializeMs(taskInterval,
[foo] // capture just foo by value (Note it would be bad to pass by reference as foo would be out of scope when the lamda function runs later)
() // No parameters to the callback
-> void // Returns nothing
{
if (foo == 123) {
debugf("lamda Callback foo is 123");
}
else
{
debugf("lamda Callback foo is not 123, crikey!");
}
})
.start();
}

#define LEDPIN_1 2 // GPIO2
#define LEDPIN_2 4 // GPIO4

LedBlinker myLed1 = LedBlinker(LEDPIN_1);
LedBlinker myLed2 = LedBlinker(LEDPIN_2);

// This example shows how to use a member function as a callback
void callMemberFunction() {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Coding-Style: Put the opening curly brace on the next line.


// A non-static member function must be called with an object.
// That is, it always implicitly passes "this" pointer as its argument.
// But because our callback specifies that we don't take any arguments (<void(void)>),
// you must use std::bind to bind the first (and the only) argument.

TimerDelegateStdFunction b = std::bind(&Task::callbackMemberFunction, this);
taskTimer.initializeMs(taskInterval, b).start();
}

void doOldDelegate()
{
debugf("doOldDelegate");
}
void callbackMemberFunction()
{
debugf("callMemberFunction");
}


private:
Timer taskTimer;
int taskInterval = 1000;

};

Task task1;
Task task2;
Task task3;
Task task4;
Task task5;

void init()
{
myLed1.setTimer(1000);
myLed1.blink(true);
myLed2.setTimer(500);
myLed2.blink(true);
WifiStation.enable(false);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove the Wifi* call on this line and the one below. They are not directly related to the example and to what you are trying to demonstrate.

WifiAccessPoint.enable(false);
Serial.begin(115200);

task1.setTimer(1500);
task1.blinkOldDelegate();

task2.setTimer(1600);
task2.callPlainOldOrdinaryFunction();

task3.setTimer(1900);
task3.showHowToUseBind();

task4.setTimer(1700);
task4.callMemberFunction();

task5.setTimer(1800);
task5.callLamda();

}