Informer - это MT-safe механизм для оповещения нескольких подписчиков о
возникшем событии.

Вопросы по Informer'у:
    * Нужно использовать Object::mutex для работы;
    * Не должно быть необходимости в создании ссылки на себя при вызове
      informAll();
    * Informer'ы должны встраиваться в coderef-контейнеры.

1. Использование Object::Mutex.

По правилам MyCpp, перед вызовом informAll() нужно освобождать все мьютексы.
Поэтому для синхронизации Informer'а можно использовать любой мьютекс.

Как передавать ссылку на подходящий мьютекс, станет ясно из ответов на остальные
вопросы.

2. Ссылка на себя в informAll().

Это - общая проблема: как гарантировать, что объект не будет удалён во время
вызова произвольного метода? Дело в том, что Ref<>, используемый для вызова
объекта - это не CodeRef, а ссылка данных. Данные могут измениться в любой
момент, и повлиять на это никак нельзя: требование свободы модификации данных.

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

Ещё один выход (неприемлемый из соображений эффективности) - создавать ссылку
на себя при входе в каждый метод.

Третий вариант - следить за возможностью удаления текущего объекта перед вызовом
асинхронного метода и создавать ссылку на себя при необходимости.

На самом деле, решение с deletion queue очень привлекательно, но оно отпугивает
необходимостью поддерживать дополнительный функционал в рантайме и привязкой
к циклической схеме работы.

Важно провести параллели с Cb<>, потому что удержание CodeRef призвано решить
ту же проблему: защитить объект от уничтожения на время вызова его метода. Общее
правило можно сформулировать так:

  || На время вызова любого асинхронного метода объекта нужно удерживать CodeRef
  || на этот объект.

При этом нужно выполнять оптимизацию по last_coderef_container. Покрывает ли это
правило все проблемные случаи, и что нужно сделать, чтобы оно соблюдалось
повсюду в MomentVideo? Каковы потери производительности на дополнительные
CodeRef'ы?

То есть появляется новый механизм async_call(). Он устанавливает CodeRef на
coderef_container и вызывает нужный метод. Похоже на Cb<>::call(), но с тем
упрощением, что ссылка на объект уже существует на момент вызова, и не нужно
захватывать CodeRef.

  || Вызов асинхронного метода - особая операция. Асинхронные методы нужно
  || вызывать с помощью механизма async_call().

Как быть с вызовом методов синхронных объектов? Где граница межу синхронными
и асинхронными методами?

Синхронные объекты синхронны только отчасти, потому что для связывания цепочек
обработки используются Cb<>, приспособленные для вызова асинхронных методов.
Также много синхронных объектов наследуют от DependentCodeReferenced, который
также является асинхронным механизмом (опирается на Object).

  || Синхронный объект - это зависимый от контейнера объект с внешней
  || синхронизацией.

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

Требование удержания CodeRef на время вызова метода применимо к любому объекту,
порождённому от CodeReferenced. Необходимость соблюдения этого правила
проявляется в основном в местах, где не может быть сделано предположений о
действиях, которые совершит метод: эти действия могут привести (и приводят) к
разрушению собственного объекта.

При соблюдении правил вызова методов обектов, производных от CodeReferenced,
удерживать дополнительную ссылку на себя Informer'у не требуется.

3. Встраивание Informer'ов в coderef-контейнеры.

Правила вызова из п.2 обеспечивают безопасность встраивания Informer'ов в
произвольный контейнер при условии, что на время вызова любого метода informer'а
удерживается CodeRef на Informer. Это слишком сильное требование. Не проще ли
создать CodeRef на себя сразу после входа в informAll()?

Если я обращаюсь к informer'у через точку (obj.informer.informAll()), то могу
быть уверен, что coderef-контейнер informer'а такой же, как и у объекта,
в котором он содержится. Informer'ам вообще необязательно наследовать от
CodeReferenced, т к реально все Informer'ы будут привязаны к базовому объекту
как данные.


Всё же можно унаследовать от CodeReferenced, чтобы получить в своё распоряжение
coderef_container, мьютекс которого можно использовать в своих целях. Но лучше
сделать это чисто: дать прямую ссылку на мьютекс (ук-ль).


Вывод:

Управление CodeRef'ами в ручном режиме - необходимое зло, чтобы писать
верифицируемые MT-safe программы с немедленным удалением объектов (без
отложенного удаления через deletion queue).

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

