Многофазная инициализация
От: enji  
Дата: 13.02.15 13:59
Оценка: 3 (1)
Вкратце о задаче — есть приложение, состоящие из кучи разных сущностей (я их называю модулями). К примеру модуль драйвера каких-то железок, журнала, таймеров, отправки смс, прикладной функциональности, общения с другим ПО, лога и т.п.

Нужные модули создаются в зависимости от конфига при старте и уничтожаются при завершении работы.

Модуль при создании создает и настраивает объекты, которые собственно будут решать задачу. Иногда для этого нужны объекты из других модулей — к примеру драйверу нужен таймер и журнал и т.п.

Как я понимаю, это что-то вроде сервис-локатора — центральное хранилище, у которого можно затребовать модуль по имени / типу, а он будет создан или выдан имеющийся.

Иногда получается многофазная инициализация — к примеру драйвер использует журнал, но ему надо зарегистрировать в журнале свои события, чтобы журнал мог подгрузить настройки регистрации этих событий.

Сейчас у меня сделано так — у модуля есть метод void load(int step), и есть шаги загрузки от 1 до 10. Система дергает все методы на шаге 1, затем на шаге 2 и т.д. А в доке написано, что скажем вызвать Journal::regEvent можно на шагах 1-5. Соответственно на шаге 6 журнал выполняет загрузку данных и попытка вызвать Journal::regEvent закончится ошибкой.

Проблема в том, что надо это все помнить и аккуратно вручную разруливать. Опять же, если придется поменять допустимые шаги для вызова метода — надо перелопатить код, который его вызывает.

Как можно сделать удобнее?
Re: Многофазная инициализация
От: Evgeny.Panasyuk Россия  
Дата: 13.02.15 14:15
Оценка:
Здравствуйте, enji, Вы писали:

E>Сейчас у меня сделано так — у модуля есть метод void load(int step), и есть шаги загрузки от 1 до 10. [...]

E>Как можно сделать удобнее?

А получится заменить void load(int step) на template<int step> void load() или нечто подобное (типа template<int step> void load(Token<step> token))?
Если да, то можно добавить требование соответствующего токена в Journal::regEvent.

Если же step это всегда runtime значение, то можно заставить пользователя его проверять. Тут недавно всплывала подобная тема: 1
Автор: jazzer
Дата: 30.01.15
, 2
Автор: Mamut
Дата: 05.02.15
, 3
Автор: jazzer
Дата: 10.02.15
.
Re: Многофазная инициализация
От: __kot2  
Дата: 13.02.15 14:23
Оценка:
Здравствуйте, enji, Вы писали:
E>Модуль при создании создает и настраивает объекты, которые собственно будут решать задачу. Иногда для этого нужны объекты из других модулей — к примеру драйверу нужен таймер и журнал и т.п.
делаете центральную точку доступа — синглон. я ее обычно называю Core
она и задает порядок инициализации

если хочется сделать порядок инициализации ну прямо сильно гибким, то делайте ленивую инициализацию — при первом обращении к Core::get_driver() или типа того

обьекты не передавайте в конструктор, а пусть они запрашиваются через Core
Re: Многофазная инициализация
От: Кодт Россия  
Дата: 13.02.15 14:37
Оценка:
Здравствуйте, enji, Вы писали:

E>Как можно сделать удобнее?


Если зависимости между модулями статические, можно их явно выписать и топологически отсортировать. (С диагностикой о циклических зависимостях).
Если зависимости постольку-поскольку (например, при старте не потребовалось ничего писать в журнал — ну и фиг с ним), — то можно ловить циклические зависимости в локаторе.
Как-то так
template<class T> struct ObjectOnDemand
{
  ObjectOnDemand() : instance_(nullptr), creating_(false) {}

  T* get()
  {
    if(!instance_)
    {
      if(creating_) throw circular_dependency_exception();
      creating_ = true;
      instance_ = make_unique<T>();
      creating_ = false;
    }
    return instance_.get();
  }
private:
  unique_ptr<T> instance_;
  bool creating_;
};

Ну там многопоточность прикрутить, атомарность, — само собой...
Перекуём баги на фичи!
Re[2]: Многофазная инициализация
От: Кодт Россия  
Дата: 13.02.15 14:41
Оценка:
К>Если зависимости между модулями статические, можно их явно выписать и топологически отсортировать. (С диагностикой о циклических зависимостях).

Причём это можно и в рантайме делать — только на ранней стадии. Когда регистрируешь модули в системе.
И только потом уже начинаешь их создавать.
Перекуём баги на фичи!
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.