-
-
Save devyte/d725e283e7eeb87af0ce6b645ad90631 to your computer and use it in GitHub Desktop.
#include "Arduino.h" | |
#include "timeout.h" | |
void runtest1() | |
{ | |
using namespace esp8266; | |
polledTimeoutOneShot timeout(3000); | |
Serial.print("before while 1\n"); | |
while(!timeout.expired()) | |
yield(); | |
Serial.print("after while 1\n"); | |
Serial.print("reset\n"); | |
timeout.reset(); | |
Serial.print("before while 2\n"); | |
while(!timeout) | |
yield(); | |
Serial.print("after while 2\n"); | |
} | |
void runtest2() | |
{ | |
using namespace esp8266; | |
polledTimeoutPeriodic timeout(3000); | |
Serial.print("before while 1\n"); | |
while(!timeout.expired()) | |
yield(); | |
Serial.print("after while 1\n"); | |
Serial.print("no reset needed\n"); | |
Serial.print("before while 2\n"); | |
while(!timeout) | |
yield(); | |
Serial.print("after while 2\n"); | |
} | |
void runtest3() | |
{ | |
using namespace esp8266; | |
polledTimeoutPeriodic timeout(1000); | |
int counter = 10; | |
while(1) | |
{ | |
if(timeout) | |
{ | |
Serial.print("*"); | |
if(!--counter) | |
break; | |
yield(); | |
} | |
} | |
Serial.println(); | |
} | |
polledTimeoutPeriodic loopTimeout(1000); | |
void setup() | |
{ | |
Serial.begin(115200); | |
delay(10); | |
Serial.println(); | |
Serial.print("runtest1\n"); | |
runtest1(); | |
Serial.print("done\n"); | |
Serial.print("runtest2\n"); | |
runtest2(); | |
Serial.print("done\n"); | |
Serial.print("runtest3\n"); | |
runtest3(); | |
Serial.print("done\n"); | |
loopTimeout.reset(); | |
} | |
void loop() | |
{ | |
if(loopTimeout) | |
Serial.print("#"); | |
} |
#ifndef __ESP8266TIMEOUT_H__ | |
#define __ESP8266TIMEOUT_H__ | |
namespace esp8266 | |
{ | |
template<bool PeriodicT> | |
class polledTimeout | |
{ | |
public: | |
using timeType = unsigned int; | |
polledTimeout(timeType timeout) | |
: _timeout(timeout), _start(millis()) | |
{} | |
bool expired() | |
{ | |
if(PeriodicT) | |
return expiredRetrigger(); | |
return expiredOneShot(); | |
} | |
operator bool() | |
{ | |
return expired(); | |
} | |
bool reset() | |
{ | |
_start = millis(); | |
} | |
protected: | |
bool checkExpired(timeType t) const | |
{ | |
return (t - _start) >= _timeout; | |
} | |
bool expiredRetrigger() | |
{ | |
timeType current = millis(); | |
if(checkExpired(current)) | |
{ | |
_start = current; | |
return true; | |
} | |
return false; | |
} | |
bool expiredOneShot() const | |
{ | |
return checkExpired(millis()); | |
} | |
timeType _timeout; | |
timeType _start; | |
}; | |
using polledTimeoutOneShot = polledTimeout<false>; | |
using polledTimeoutPeriodic = polledTimeout<true>; | |
} | |
#endif |
This deserves a PR on @arduino's repo
Looks great and I like the usage model, but I can foresee people creating the object waaaaay before using it and having it fail on the first call since the constructor was called XXXms ago. Not sure how to guard against it, other than stressing that you make the new object right before using it...
Minor vote against time_t
since that is traditionally used to store seconds, not milliseconds. uint32_t
or unsigned long
is your friend (and the return type of millis()
)
@earlephilhower Sure, some users will make the mistake, but then they can get referred to RAII.
About time_t, you're right, and the internal type isn't visible anyways.
@d-a-v I implemented with RAII in mind, so it's really meant for stack declaration, ideally within a specific scope. Given that, there is no difference between 2 uints within the class vs. 1 uint in the class and 1 int passed as argument: both cases eventually allocate 2 uints on the stack. The only difference would be in the case when an object is declared globally, then you'd have one uint in the (global) heap and one in the stack.
I think two uints in the stack is better.
Also, the current way shown by @earlephilhower:
uint32_t start = millis();
while (millis() - start < timeout)
{....}
uses 1 uint on the stack plus 1 temp uint also on the stack, so the same :p
What about moving yield() in expired() ? (or optimistic_yield())
reset() could be
reset(something)
instead, with still only one variable.