/*!
\page oess_1_4_0__stdsn__shptr_skeleton	oess_1.4.0.	Базовый каркас для умных указателей


\section oess_1_4_0__stdsn__shptr_skeleton__history Немного истории

Первоначально в ObjESSty появился класс oess_1::stdsn::shptr_t для
решения проблемы умных указателей. Подробнее о причинах его появления
можно прочитать в \ref stdsn_shptr. Со временем возможностей базовой
реализации oess_1::stdsn::shptr_t стало не хватать.

Во-первых, в некоторых случаях для защиты умных указателей в многопоточных
приложениях использовался не механизм подсчета ссылок, а механизм
клонирования объектов, на которые указывали умные указатели. Для этого
класс oess_1::stdsn::shptr_t был расширен несколькими методами
(oess_shptr_assign, oess_shptr_reset) с тем, чтобы их можно было
переопределять в производных классах.

Во-вторых, в v.1.2.0 появился механизм
\ref oess_1_2_0__subclassing_by_extension. Для работы с объектами, которые
поддерживают этот механизм так же требовалось использовать атрибуты-указатели.
И для облегчения работы с ними так же требовался класс умного указателя. Но
применить для этих целей oess_1::stdsn::shptr_t было невозможно. Дело в том,
что oess_1::stdsn::shptr_t представлялся в DDL как:
\verbatim
{type oess_1::stdsn::shptr_t
  {attr m_ptr {of {ptr} oess_1::stdsn::serializable_t} }
}
\endverbatim
Т.е. shptr_t позволял использовать одинаковое DDL-представление для всех
сериализуемых типов.
Но для типов с subclassing by extension умный указатель в DDL должен был
выглядеть так:
\verbatim
{type some_smart_pointer_t
	{attr	m_ptr {of {extension_of} some_type_t}}
}
\endverbatim
Причем в качестве some_type_t нельзя было указывать имя
oess_1::stdsn::serializable_t, т.к. он не входит в иерархию 
subclassing by extension.

Для того, чтобы поддержать умные указатели для механизма
subclassing by extension потребовалось бы создать новый тип умных указателей.
Но зачем же иметь в ObjESSty несколько разных классов с одинаковой
функциональностью и предназначенных для одинаковых целей? Вместо этого
был создан каркас для умных указателей, oess_1::stdsn::shptr_skeleton_t,
который можно использовать для поддержки механизма subclassing by
extension. А так же класс oess_1::stdsn::shptr_t сделан наследником
oess_1::stdsn::shptr_skeleton_t для того, чтобы унаследовать всю
имеющуюся функциональность.

\section oess_1_4_0__stdsn__shptr_skeleton__shptr_skeleton Класс shptr_skeleton_t

Класс oess_1::stdsn::shptr_skeleton_t является абстрактным классом, который
должен быть непосредственным базовым классом для конкретных классов
умных указателей. Т.е. класс умного указателя должен быть произведен
не от oess_1::stdsn::serializable_t, а от oess_1::stdsn::shptr_skeleton_t.

Класс oess_1::stdsn::shptr_skeleton_t содержит функциональность по
управлению хранимым в нем указателем, но не имеет собственного DDL описания.
Атрибут oess_1::stdsn::shptr_skeleton_t::m_ptr (указатель на контролируемый
объект) должен быть объявлен в DDL описании производного от
shptr_skeleton_t класса.

Класс shptr_skeleton_t поддерживает разные политики владения указателем.
Т.е. он может использоваться как для реализации владения на основе
подсчета ссылок, на основе клонирования объекта, на основе реализованной
пользователем политики. Для этого одним из параметров шаблона
oess_1::stdsn::shptr_skeleton_t является класс Own_policy. Класс
shptr_skeleton_t владеет атрибутом m_own_policy, который и является
реальной политикой, управляющей временем жизни контролируемого объекта.
Меняя при инстанциировании shptr_skeleton_t типы политик можно достигать
разного поведения shptr_skeleton_t. Подробнее о политиках владения
см. \ref oess_1_4_0__stdsn__shptr_skeleton__policies.

\section oess_1_4_0__stdsn__shptr_skeleton__usage	Использование shptr_skeleton_t для создания собственного умного указателя

Для того, чтобы создать собственный умный указатель на основе
shptr_skeleton_t нужно сделать две вещи:

\b 1. Описать на DDL схему данных умного указателя. Обязательно указать в ней
	атрибут m_ptr соотвествующего типа. Например, для простых умных
	указателей:
\verbatim
{type	my_smart_ptr_t
	{attr m_ptr {of {ptr} my_class_t}}
}
\endverbatim
	или для механизма subclassing by extension:
\verbatim
{type	my_smart_ptr_t
	{attr m_ptr {of {extension_of} my_class_t}}
}
\endverbatim

	Важно здесь вот что:
- отсутствие указания базового типа (тега {super}). В результате для механизма
сериализации ObjESSty типа shptr_skeleton_t в иерархии не существует, ObjESSty
предполагает, что my_smart_ptr_t унаследованн сразу от serializable_t;
- обязательное указание атрибута m_ptr. Именно этот атрибут будет затем
контролироваться политикой владения.

\b 2. Описать на C++ свой класс умного указателя следующим образом:
\code
class	my_smart_ptr_t
	:	public oess_1::stdsn::shptr_skeleton_t< my_class_t >
	{
		// Может так же использоваться макрос OESS_SERIALIZER_EX().
		OESS_SERIALIZER( my_smart_ptr_t )
		OESS_1_SHPTR_IFACE( my_smart_ptr_t, my_class_t,
				oess_1::stdsn::shptr_skeleton_t< my_class_t > )
	};
\endcode
	Причем при описании класса на C++ не важно, поддерживает ли он
	обычные указатели или указатели для механизма subclassing by
	extension.

\section oess_1_4_0__stdsn__shptr_skeleton__policies Политики владения

Политика владения -- это объект, который отвечает за уничтожение контролируемого
умным указателем объекта в нужный момент времени. Политика задается классу
shptr_skeleton_t параметром шаблона. Класс политики владения должен
удовлетворять интерфейсу:
\code
template< class T >
class	policy_t
	{
	public :
		policy_t( T * & pointer_holder );

		policy_t(
			T * & pointer_holder, T * pointer );

		~policy_t();

		void
		reassign();

		void
		link(
			const policy_t< T > & owner_policy );

		std::auto_ptr< T >
		release();
	};
\endcode

Фокус с объектами-политиками состоит в том, что им класс shptr_skeleton_t
передает ссылку на свой атрибут m_ptr. И объекты-политики должны корректно
устанавливать или обнулять его значение. Практически во всех случаях именно
объект-политика устанавливает значение атрибута m_ptr (в своих конструкторах,
методах link и release). Единственным исключением является метод
reassign, но о нем речь зайдет ниже.

Первый конструктор необходим для случая, когда shptr_skeleton_t инициализируется
конструктором по-умолчанию.

Второй конструктор необходим, когда в конструктор shptr_skeleton_t передается
объект, которым никто не владеет. Единственным владельцем должен стать
данный объект-политика.

Метод link вызывается в операторе копирования класса shptr_skeleton_t.
Его атрибутом является объект-политика из объекта shptr_skeleton_t в
правой части присваивания.

Метод release() вызывается либо из метода
oess_1::stdsn::shptr_skeleton_t::destroy() (когда пользователь хочет отказаться
от владения объектом), либо из метода
oess_1::stdsn::shptr_skeleton_t::oess_pre_unpack() (когда текущий контролируемый
объект становится неактуальным, т.к. после десериализации контролируемым
должен стать другой объект). Должен вовращаться std::auto_ptr, в котором
находится указатель на ранее контролировавшийся объект, если его больше
никто не контролирует (т.е. объект будет уничтожен std::auto_ptr). Либо в
std::auto_ptr должен быть нулевой указатель (т.е. объект продолжает
контролировать кто-то еще и объект не может быть физически уничтожен).

Отдельная ситуация с методом reassign(). В большинстве случаев именно
объект-политика управляет значением атрибута m_ptr класса shptr_skeleton.
Но есть одно исключение -- при десериализации объекта значение атрибута
m_ptr устанавливается самой ObjESSty. Поэтому в методе
oess_1::stdsn::shptr_skeleton_t::oess_post_unpack() вызывается метод
reassign() чтобы объект-политика могла создать всю необходимую инфраструктуру
для котроля за новым объектом.

\subsection oess_1_4_0__stdsn__shptr_skeleton__policies__refcountable Политика на основе счетчика ссылок

Политика на основе подсчета количества ссылок на объект реализуется классом
oess_1::stdsn::refcountable_policy_t. Это политика, которая используется
классом shptr_skeleton_t по умолчанию.

\subsection oess_1_4_0__stdsn__shptr_skeleton__policies__cloneable Политика на основе клонирования

Политика на основе клонирования реализуется классом
oess_1::stdsn::cloneable_policy_t. Принцип ее работы прост: когда требуется
создать копию умного указателя, для новой копии создается новая копия
контролируемого объекта (путем клонирования).

Для того, чтобы тип мог использоваться совместно с политикой
cloneable_policy_t необходимо, чтобы он предоставлял метод:
\code
T *
clone() const;
\endcode
который бы возвращал указатель на новый динамически созданный объект.

Либо, метод clone() может иметь следующий прототип:
\code
std::auto_ptr< T >
clone() const;
\endcode

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

\section oess_1_4_0__stdsn__shptr_skeleton__shptr_changes	Изменения в shptr

В версии 1.4.0 класс oess_1::stdsn::shptr_t был изменен: он сделал производным
от oess_1::stdsn::shptr_skeleton_t (с политикой на основе подсчета ссылок) и
из него удалены все методы за исключением конструкторов и оператора копирования.
Это означает, что весь код, который оработат на основе старых методов
oess_shptr_assign, oess_shptr_reset при переходе на 1.4.0 должен быть
переписан.

Для остальных клиентов класса shptr_t будет видно только одно изменение:
методы get() теперь порождают исключения, если приведение типов невозможно.
В предыдущих версиях shptr_t в таких случаях возвращался нулевой указатель.

*/
