Essa é minha implementação de um pequeno sistema de agendamento de tarefas, que futuramente usarei em um outro projeto, achei que ficou legal então resolvi postar. Vamos à implementação
task.hpp
#ifndef _task_hpp
#define _task_hpp
#include <ctime>
#include <boost /function.hpp>
#include </boost><boost /bind.hpp>
class task
{
public:
explicit task(const boost::function<void ()>& callback)
: _call_back(callback)
, _call_count(0)
, _total_time_used(0)
{
}
virtual ~task() { }
virtual void before_task() { }
void do_task()
{
before_task();
_call_back();
after_task();
}
virtual void after_task() { }
void set_callback(const boost::function</void><void ()>& callback)
{
_call_back = callback;
}
const boost::function</void><void ()>& get_callback() const
{
return _call_back;
}
bool is_valid() const
{
return true;
}
private:
boost::function</void><void ()> _call_back;
std::size_t _call_count;
std::clock_t _total_time_used;
};
#endif
schedule.hpp
#ifndef _schedule_hpp
#define _schedule_hpp
#include <algorithm>
#include <deque>
#include <boost /pool/pool_alloc.hpp>
#include </boost><boost /shared_ptr.hpp>
#include </boost><boost /noncopyable.hpp>
#include </boost><boost /thread/thread.hpp>
#include </boost><boost /thread/xtime.hpp>
#include </boost><boost /thread/mutex.hpp>
#include "task.hpp"
using std::for_each;
using std::deque;
using boost::shared_ptr;
class task;
typedef shared_ptr<task> task_ptr;
typedef deque<task_ptr , boost::pool_allocator<task_ptr> > deque_task;
class schedule : public boost::noncopyable
{
public:
schedule() : job(boost::bind(&schedule::thread_dispatcher, this))
{
_thread_sleep.sec = 10;
try
{
job.join();
}
catch (boost::thread_interrupted&) { /* don't care... */ }
}
virtual ~schedule() { }
void add_task(const shared_ptr<task>& _task)
{
boost::mutex::scoped_lock lock(monitor);
deque_task::const_iterator it = std::find(_task_pool.begin(),
_task_pool.end(), _task);
if (it == _task_pool.end())
{
_task_pool.push_back(_task);
}
else {
// duplicate item
}
}
void remove_task(const shared_ptr</task><task>& _task)
{
boost::mutex::scoped_lock lock(monitor);
deque_task::iterator it = std::find(_task_pool.begin(),
_task_pool.end(), _task);
if (it != _task_pool.end())
{
_task_pool.erase(it);
}
else {
// does't exist
}
}
protected:
void thread_dispatcher()
{
for (;;)
{
for_each(_task_pool.begin(), _task_pool.end(),
boost::mem_fn(&task::do_task));
boost::thread::sleep(_thread_sleep);
}
}
private:
deque_task _task_pool;
boost::thread job;
boost::mutex monitor;
boost::xtime _thread_sleep;
};
#endif
Unidade para testes, main.cpp
#include <iostream>
#include <boost /scoped_ptr.hpp>
#include </boost><boost /bind.hpp>
#include "schedule.hpp"
void f1()
{
std::cout < < "f1()" << std::endl;
}
void f2()
{
std::cout << "f2()" << std::endl;
}
int main()
{
boost::scoped_ptr<schedule> _schedule(new schedule());
shared_ptr<task> _task1 (new task(f1));
shared_ptr</task><task> _task2 (new task(f2));
_schedule->add_task(_task1);
_schedule->add_task(_task1); // repetido, nao insere...
_schedule->add_task(_task2);
_schedule->start();
return 0;
}
Agradecimentos
- Daniel pela sugestão de usar fila e apenas uma thread ao invés de uma para cada tarefa e assim evitando busy-waiting
- Alex pelos testes de compatibilidade com mingw e msvc (vide mem_fun e shared_ptr)
schedule.zip (arquivo não recuperado)
Discussão preservada
0 comentários
Nenhum comentário foi registrado ou recuperado para este post.