Пустые обертки для не пустых функций с аргументом

Итак, у меня следующая ситуация:

  • Я пишу для онлайн-компилятора mbed на микроконтроллере с малым объемом памяти.

  • Производительность в реальном времени очень важна, я хочу, чтобы это занимало меньше микросекунды. 10 микросекунд будут терпимы.

  • Я использую их библиотеку тайм-аутов, которая предоставляет API для вызова ISR после указанного времени, но требует, чтобы ISR была функцией void / void. (включая функцию-член.

    void TimeoutCallback(void) { do stuff that I want to do on timeout.} // ISR
    
    Timeout to;
    to.attach_us(&TimeoutCallback, 750) // Call TimeoutCallback in 750 us.
    
  • Я создал вектор объектов Timeout, которые все устанавливаются одновременно для одной и той же функции с разным количеством времени. Я хочу как-то перейти в TimeoutCallback который Объект таймаута вызвал это.

Сначала я задумался о том, чтобы перегрузить класс Timeout, чтобы он мог принимать указатели на функции int (int) и принимать число в перегруженной функции присоединения, которая передается указателю на указанную функцию. Однако я не уверен, является ли это на самом деле практичным, учитывая беспорядочное (и зависящее от устройства) наследование класса Timeout.

Теперь мне интересно, есть ли способ программно создать функцию void / void, которая оборачивает функцию void / int и включает переменную ссылку int, которая передается в обернутую функцию.

1

Решение

Поскольку ваша библиотека может вызывать функции-члены, вы можете создать адаптер …

template <typename Func, Func func>
struct Adapter
{
Adapter(int n) : n_(n) { }

void f() { func(n_); }
int n_;
};

Чтобы использовать это:

Adapter<void(*)(int), My_Function_Expecting_An_Int> adapter(the_int);
to.attach_us(&adapter, &decltype(adapter)::f, timeout_us);

Убедитесь, что adapterВремя жизни длится до обратного вызова ….


Чтобы вызвать функцию-член:

#include <iostream>
#include <string>
#include <vector>

struct MyObj
{
void f(int n) { std::cout <<"hi " << n << "\n"; }
};

template <typename Class, typename PFunc>
struct Adapter
{
Adapter(Class& object, PFunc pFunc, int n) : object_(object), pFunc_(pFunc), n_(n) { }

void f() { (object_.*pFunc_)(n_); }

Class& object_;
PFunc pFunc_;
int n_;
};

int main()
{
MyObj myObj;

Adapter<MyObj, void(MyObj::*)(int)> adapter(myObj, &MyObj::f, 43);
adapter.f();
}
0

Другие решения

Хотя решение Тони Ди уместно, если вы используете mbed Ticker класс, есть альтернативный метод, использующий mbed RtosTimer.

RtosTimer Конструктор занимает void* аргумент, который передается обработчику по таймауту. Обработчик имеет подпись:

void handler(void const* n)

куда n является аргументом указателя, передаваемым конструктору и может использоваться для идентификации определенного времени ожидания.

В отличие от Ticker где функция тайм-аута выполняется в контексте прерывания, для RtosTimer обработчик работает как поток, что дает большую гибкость, но потенциально большую задержку.

1

По вопросам рекламы [email protected]