Вопрос

У меня есть класс A и список объектов A.A имеет функцию f, которая должна выполняться каждые X секунд (для первого экземпляра каждую 1 секунду, для второго экземпляра каждые 5 секунд и т. д.).У меня есть класс планировщика, который отвечает за выполнение функций в нужное время.Я решил создать новый класс ATime, который будет содержать ptr для экземпляра A и время выполнения A::f.Планировщик будет удерживать очередь Atime с минимальным приоритетом.

  1. Как вы думаете, это правильная реализация?
  2. Должен ли ATime быть вложенным классом планировщика?
Это было полезно?

Решение

Судя по тому, что вы описываете, это может сработать :-)

ИМХО класс ATime принадлежит планировщику больше, чем A.Это необходимо планировщику для выполнения своей работы, и оно не нужно для А.На самом деле, A (и остальному миру) даже не обязательно знать о его существовании — поэтому для меня было бы уместно поместить его в частный вложенный класс планировщика.

Другие советы

Возможно, это слишком продвинуто, но вот...

повышение::функция и повышение::связывание может использоваться для реализации планировщика, которому не нужно ничего знать о классе A.Это сделает ваш планировщик более универсальным и пригодным для повторного использования.

Вот пример кода, который иллюстрирует, как эти возможности Boost можно использовать в вашем случае:

#include <ctime>
#include <queue>
#include <boost/function.hpp>
#include <boost/bind.hpp>

struct Foo
{
    void onScheduler(time_t time) {/*...*/}
};

struct Bar
{
    void onScheduler(time_t time) {/*...*/}
};

typedef boost::function<void (time_t)> SchedulerHandler;

struct SchedulerEvent
{
    bool operator<(const SchedulerEvent& rhs) const {return when < rhs.when;}

    SchedulerHandler handler;
    time_t when;
};

class Scheduler
{
public:
    void schedule(SchedulerHandler handler, time_t when)
    {
        SchedulerEvent event = {handler, when};
        queue_.push(event);
    }

private:
    std::priority_queue<SchedulerEvent> queue_;
    void onNextEvent()
    {
        const SchedulerEvent& next = queue_.top();
        next.handler(next.when);
        queue_.pop();
    }
};

int main()
{
    Scheduler s;
    Foo f1, f2;
    Bar b1, b2;

    time_t now = time(0);
    s.schedule(boost::bind(&Foo::onScheduler, &f1, _1), now + 1);
    s.schedule(boost::bind(&Foo::onScheduler, &f2, _1), now + 2);
    s.schedule(boost::bind(&Bar::onScheduler, &b1, _1), now + 3);
    s.schedule(boost::bind(&Bar::onScheduler, &b2, _1), now + 4);

    // Do scheduling...

    return 0;
}

Обратите внимание, что Scheduler ничего не знает о Foo & Bar, и наоборот.Все Scheduler действительно хочет — это функтор «обратного вызова», который соответствует сигнатуре, указанной SchedulerHandler.

Если вам нужен SchedulerEvent быть отмененным, все становится немного сложнее, потому что boost::function объекты несопоставимы.Чтобы обойти эту проблему, вам нужно будет вернуть какой-то токен «соединения» при регистрации событий.По сути, это то, что делает Boost.Signal.

Надеюсь это поможет.

Этот тип класса лучше всего сделать частной структурой, вложенной в ваш класс планировщика, чтобы вы могли легко получить доступ ко всем полям внутри класса планировщика.(Все поля структуры по умолчанию являются общедоступными.)

Что касается второй части (и вопроса в заголовке), то, по моему мнению, это полностью дело вкуса.С тем же успехом вы могли бы уменьшить беспорядок в определении класса Scheduler и поместить ATime в подпространство имен с именем предупреждения (например, detail), чтобы люди не использовали его.В конце концов, если это полезно только для Планировщика, нет необходимости слишком сильно его скрывать — все равно никто не захочет его использовать.

Возможно, в C++0x все может быть по-другому (мне кажется, я слышал некоторые слухи о том, как будут изменены правила доступности между вложенным и родительским классом или около того, и в этом случае вложение может быть более целесообразным).

Для универсальности вы также можете использовать шаблоны и, возможно, в конечном итоге получить Scheduler<A> (используя TimedOperation<A>) (или множество потенциальных усовершенствований/обобщений этого)?

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top