Skip to content

Allow environment capture in lambda callbacks#19

Merged
Aasim-A merged 3 commits intoAasim-A:masterfrom
c-jiph:master
May 29, 2022
Merged

Allow environment capture in lambda callbacks#19
Aasim-A merged 3 commits intoAasim-A:masterfrom
c-jiph:master

Conversation

@c-jiph
Copy link
Contributor

@c-jiph c-jiph commented Mar 13, 2022

Thank you for making this library, it's been really helpful for a small project of mine.

This PR adds the ability to capture variables in lambdas used as timer callbacks. For example:

AsyncTimer t;

void foo(int v) {
  t.setTimeout([=]() {
    Serial.print("Got value ");
    Serial.println(v, DEC);
  }, 1000);
}

Without something like this PR, the above will fail with an error like:

Example.ino: In function 'void foo(int)':
Example:12:10: error: no matching function for call to 'AsyncTimer::setTimeout(foo(int)::<lambda()>, int)'
   }, 1000);
          ^
In file included from Example.ino:4:0:
/home/c-jiph/Arduino/libraries/AsyncTimer/src/AsyncTimer.h:77:18: note: candidate: short unsigned int AsyncTimer::setTimeout(AsyncTimer::Callback, long unsigned int)
   unsigned short setTimeout(Callback callback, unsigned long ms);
                  ^~~~~~~~~~
/home/cjiph/Arduino/libraries/AsyncTimer/src/AsyncTimer.h:77:18: note:   no known conversion for argument 1 from 'foo(int)::<lambda()>' to 'AsyncTimer::Callback {aka void (*)()}'
exit status 1
no matching function for call to 'AsyncTimer::setTimeout(foo(int)::<lambda()>, int)'

Note this actually fixes the existing example CancelTimeoutExample.ino which currently does not compile in master.

I've also included a macro option LITE_CALLBACK_SUPPORT which enables the old implementation which will save a small amount of code and data storage for highly constrained projects.

@Aasim-A
Copy link
Owner

Aasim-A commented Mar 23, 2022

Hi Jacob, thanks for the PR, my concern is that this may not work with arduino boards because they might not support std::function have you tested that?

@c-jiph
Copy link
Contributor Author

c-jiph commented Mar 27, 2022

Ah, you are absolutely right. The project I was working on is actually for an Arm-based Arduino board, not AVR. After checking I see STL is not available in the Arduino IDE for AVR boards.

The AVR compiler is still fully gcc with C++ backed, so I was able to update my PR to make this work without STL. The change is quite a bit more involved though. Essentially I've created a very simple replacement for std::function which only supports holding lambdas/pointers to functions with no args and no return. I got the core ideas from https://www.codeproject.com/Articles/313312/Cplusplus11-Lambda-Storage-Without-libcplusplus

It's not ... beautiful, but seems to work and I've verified it on an Arduino Uno board. The most annoying part is not having things like std::move or std::swap so there are a few more copies than I'd like.

What do you think?

@tamtakoe
Copy link

@Aasim-A any comments?

@VladislavSmolyanoy
Copy link

Works perfectly on an ESP32

@Aasim-A
Copy link
Owner

Aasim-A commented May 6, 2022

Hi, sorry I've been super busy lately, I'll look more into this and try to merge it into the library.

Thanks again for the PR

@Aasim-A
Copy link
Owner

Aasim-A commented May 29, 2022

@c-jiph Sorry this took this long, thanks a lot for putting the time to implement this 🙂

@Aasim-A Aasim-A merged commit fc9b1b4 into Aasim-A:master May 29, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants