From 18f77964b4d00a2afcbede1aaa117c06b82181dd Mon Sep 17 00:00:00 2001 From: frank eden <frank.eden@gmail.com> Date: Mon, 14 May 2018 21:57:15 +1000 Subject: [PATCH 1/3] Make sample show more examples of std::function and std::bind --- Sming/SmingCore/Timer.cpp | 32 +++++ Sming/SmingCore/Timer.h | 34 ++++- samples/Basic_Delegates/app/application.cpp | 138 ++++++++++++++++---- 3 files changed, 169 insertions(+), 35 deletions(-) diff --git a/Sming/SmingCore/Timer.cpp b/Sming/SmingCore/Timer.cpp index 2e6ac3690b..5fd2041a2b 100644 --- a/Sming/SmingCore/Timer.cpp +++ b/Sming/SmingCore/Timer.cpp @@ -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; @@ -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) @@ -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) @@ -197,6 +225,10 @@ void Timer::tick() { delegate_func(); } + else if (delegate_stdfunc) + { + delegate_stdfunc(); + } else{ stop(); } diff --git a/Sming/SmingCore/Timer.h b/Sming/SmingCore/Timer.h index 247c5ef6cb..7504f4a37a 100644 --- a/Sming/SmingCore/Timer.h +++ b/Sming/SmingCore/Timer.h @@ -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" @@ -25,6 +25,7 @@ #define MAX_OS_TIMER_INTERVAL_US 268435000 typedef Delegate<void()> TimerDelegate; +typedef std::function<void()> TimerDelegateStdFunction; class Timer { @@ -59,6 +60,7 @@ 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. @@ -66,9 +68,23 @@ class 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. */ @@ -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: @@ -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; diff --git a/samples/Basic_Delegates/app/application.cpp b/samples/Basic_Delegates/app/application.cpp index 95f494c427..ac0869b48a 100644 --- a/samples/Basic_Delegates/app/application.cpp +++ b/samples/Basic_Delegates/app/application.cpp @@ -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) { - 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() { + 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() { + 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() { + 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() { + + // 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); + 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(); + } From d27c56821a44d83be696ec01ae4ed9635bbf2e46 Mon Sep 17 00:00:00 2001 From: frank eden <frank.eden@gmail.com> Date: Mon, 14 May 2018 22:34:14 +1000 Subject: [PATCH 2/3] Tidy up sample --- samples/Basic_Delegates/app/application.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/samples/Basic_Delegates/app/application.cpp b/samples/Basic_Delegates/app/application.cpp index ac0869b48a..d832ee3bf7 100644 --- a/samples/Basic_Delegates/app/application.cpp +++ b/samples/Basic_Delegates/app/application.cpp @@ -27,7 +27,7 @@ class Task } // This example show the way delegates have been used in Sming in the past. - void blinkOldDelegate() { + void callOldDelegate() { taskTimer.initializeMs(taskInterval, TimerDelegate(&Task::doOldDelegate, this)).start(); } @@ -103,12 +103,10 @@ Task task5; void init() { - WifiStation.enable(false); - WifiAccessPoint.enable(false); Serial.begin(115200); task1.setTimer(1500); - task1.blinkOldDelegate(); + task1.callOldDelegate(); task2.setTimer(1600); task2.callPlainOldOrdinaryFunction(); From 82628637ca24e54936fbda0e1e7e71ebd5f7257e Mon Sep 17 00:00:00 2001 From: frank eden <frank.eden@gmail.com> Date: Tue, 15 May 2018 17:27:33 +1000 Subject: [PATCH 3/3] Apply coding standards --- samples/Basic_Delegates/app/application.cpp | 52 ++++++++++----------- 1 file changed, 24 insertions(+), 28 deletions(-) diff --git a/samples/Basic_Delegates/app/application.cpp b/samples/Basic_Delegates/app/application.cpp index d832ee3bf7..e163b22194 100644 --- a/samples/Basic_Delegates/app/application.cpp +++ b/samples/Basic_Delegates/app/application.cpp @@ -6,19 +6,17 @@ void plainOldOrdinaryFunction() debugf("plainOldOrdinaryFunction"); } - void functionWithMoreComlicatedSignature(int a, String b) { debugf("functionWithMoreComlicatedSignature %d %s", a, b.c_str()); } - class Task { - public: Task() {}; - bool setTimer(int reqInterval) { + bool setTimer(int reqInterval) + { if (reqInterval <= 0) { return false; } @@ -27,49 +25,50 @@ class Task } // This example show the way delegates have been used in Sming in the past. - void callOldDelegate() { + void callOldDelegate() + { taskTimer.initializeMs(taskInterval, TimerDelegate(&Task::doOldDelegate, this)).start(); } // This example shows how to use a plain old ordinary function as a callback - void callPlainOldOrdinaryFunction() { + void callPlainOldOrdinaryFunction() + { 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() { + void showHowToUseBind() + { 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() { + void callLamda() + { 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 + () // 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!"); + if (foo == 123) { + debugf("lamda Callback foo is 123"); + } + else + { + debugf("lamda Callback foo is not 123, crikey!"); + } } - }) - .start(); + ).start(); } - - - + // This example shows how to use a member function as a callback - void callMemberFunction() { - + void callMemberFunction() + { // 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)>), @@ -87,12 +86,10 @@ class Task { debugf("callMemberFunction"); } - - + private: Timer taskTimer; int taskInterval = 1000; - }; Task task1; @@ -119,5 +116,4 @@ void init() task5.setTimer(1800); task5.callLamda(); - }