Я пытаюсь построить очень простой планировщик. Он позволяет добавлять задачи (функции) в список и запускать их через заданные интервалы. Класс «Планировщик» работает нормально, если я предоставляю статическую функцию в качестве аргумента ее члену «ScheduleTask».
class TestController
{
private:
Scheduler _scheduler;
public:
TestController(void)
{
_scheduler.ScheduleTask(Task1, 3000);
_scheduler.ScheduleTask(Task2, 5000);
}
~TestController(void);
void Task1(void) { }
void Task2(void) { }
};
struct Task
{
long interval;
long last_run;
void (*TaskCallback) (void);
Task()
{
last_run = 0;
}
};
class Scheduler
{
private:
std::vector<Task> _tasks;
public:
Scheduler(void) { }
~Scheduler(void) { }
void ScheduleTask(void (*TaskCallback) (void), long interval)
{
Task t;
t.TaskCallback = TaskCallback;
t.interval = interval;
_tasks.push_back(t);
}
void loop()
{
for(unsigned int i = 0; i < _tasks.size(); i++)
{
long elapsed = clock();
if(elapsed - _tasks[i].last_run >= _tasks[i].interval)
{
_tasks[i].last_run = elapsed;
_tasks[i].TaskCallback();
}
}
}
};
Как я могу изменить обратный вызов так, чтобы он принимал член уже созданного объекта TestController?
Используйте комбинацию boost::function
а также boost::bind
, В качестве альтернативы используйте std::function
а также std::bind
если ваш компилятор их поддерживает.
#include <boost/bind.hpp>
#include <boost/function.hpp>
#include <vector>
typedef boost::function<void()> Callback;
struct Task
{
long interval;
long last_run;
Callback TaskCallback;
Task()
{
last_run = 0;
}
};
class Scheduler
{
private:
std::vector<Task> _tasks;
public:
Scheduler(void) { }
~Scheduler(void) { }
void ScheduleTask(const Callback& TaskCallback, long interval)
{
Task t;
t.TaskCallback = TaskCallback;
t.interval = interval;
_tasks.push_back(t);
}
void loop()
{
for(unsigned int i = 0; i < _tasks.size(); i++)
{
long elapsed = clock();
if(elapsed - _tasks[i].last_run >= _tasks[i].interval)
{
_tasks[i].last_run = elapsed;
_tasks[i].TaskCallback();
}
}
}
};
class TestController
{
private:
Scheduler _scheduler;
public:
TestController(void)
{
_scheduler.ScheduleTask(boost::bind(&TestController::Task1,this), 3000);
_scheduler.ScheduleTask(boost::bind(&TestController::Task2,this), 5000);
}
~TestController(void);
void Task1(void) { }
void Task2(void) { }
};
Других решений пока нет …