C++

Agendamento de Tarefas

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

C++
#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

C++
#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

C++
#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)

Fonte arquivística

Conteúdo recuperado via Wayback Machine, captura 20080705192754.

Abrir registro original ↗

Discussão preservada

0 comentários

Nenhum comentário foi registrado ou recuperado para este post.