arkhipenko / TaskScheduler

Cooperative multitasking for Arduino, ESPx, STM32, nRF and other microcontrollers
http://playground.arduino.cc/Code/TaskScheduler
BSD 3-Clause "New" or "Revised" License
1.21k stars 221 forks source link

`_TASK_STD_FUNCTION` should be for everyone. #184

Open issuefiler opened 5 months ago

issuefiler commented 5 months ago

The development environment

I’m working with Raspberry Pi Pico W’s on PlatformIO and my development environment is capable of building C++23 code. It has ARDUINO_ARCH_RP2040 defined and the __cplusplus expands to 202100L.

The problem

The documentation instructs to define _TASK_STD_FUNCTION in order to enable the support for std::function callbacks. However, defining it produces an error on my environment because of this microcontroller limitation.

https://github.com/arkhipenko/TaskScheduler/blob/4ccca1ac3d63a2b6fa853df3c93147fa4e8980da/src/TaskScheduler.h#L285-L290

Why std::function callbacks are needed

This is necessary to call non-static class methods.

Buzzer(const std::uint8_t pin_number) noexcept
    : pin_number{pin_number},
    task{
        TaskScheduler::immediate,
        TaskScheduler::forever,
        [this](void) -> void {this->play_the_next_note();},
        &(TaskScheduler::scheduler)
    } {
}

My suggestion

It’s all about std::function.

https://github.com/arkhipenko/TaskScheduler/blob/4ccca1ac3d63a2b6fa853df3c93147fa4e8980da/src/TaskSchedulerDeclarations.h#L125-L134

It might be more prudent to use the __cplusplus and __has_cpp_attribute for the C++ feature detection, instead of endlessly expanding the whitelist for future devices.

My temporary solution

The code works flawlessly with #define ARDUINO_ARCH_STM32.

// TaskScheduler.cpp
// Written on January 28, February 12, 24, March 2, 4, 7, 9–11, and 16, 2024.
////////////////////////////////////// 80 //////////////////////////////////////

module;

#define _TASK_SLEEP_ON_IDLE_RUN
#define _TASK_STD_FUNCTION
    // Enable the support for “std::function” callbacks.
#define ARDUINO_ARCH_STM32 // Disguising as an STM32 microcontroller
    // to suppress the “Support for std::function
    // only for ESP8266 or ESP32 architecture” error.
#include <TaskScheduler.h> // Task, Scheduler, TASK_IMMEDIATE, TASK_FOREVER.
#undef ARDUINO_ARCH_STM32

export module TaskScheduler;

export namespace TaskScheduler {
    inline constexpr unsigned long int immediate{TASK_IMMEDIATE};
    inline constexpr long int forever{TASK_FOREVER};

    using Task = ::Task;

    ::Scheduler scheduler;

    inline bool execute(void) {
        // “true” if it has called a task callback.
        return !(TaskScheduler::scheduler.execute());
    }
};