RefBase.h

См. документацию.
00001 /*
00002  * CntmLib - Подсчет ссылок, потоки, синхронизация, асинхронные процедуры, события
00003  * Copyright (c) 2005, Овсеевич Роман, CntmLib@mail.ru
00004  * _______________________________________________________________________________
00005  * Разрешено свободное использование, копирование, распространение, изменение
00006  * (изменение сведений об авторских правах запрещено). Запрещена продажа и 
00007  * включение всей библиотеки или ее частей в другие библиотеки. В сведениях об
00008  * авторских правах на программу (или сведениях о программе, об авторах, 
00009  * использованных средствах разработки и т.д.) должна быть указана информация
00010  * о библиотеке CntmLib, ее авторе и, возможно, сайте или email'е.
00011  * Библиотека поставляется "как есть", без каких-либо гарантий со стороны автора.
00012  */ 
00013 
00014 #ifndef CNTM_REFBASE_H
00015 #define CNTM_REFBASE_H
00016 #include <Cntm/RefCount/IRefObject.h>
00017 #include <Cntm/RefCount/RefObjectUsedException.h>
00018 
00019 namespace Cntm
00020 {
00021 
00022         namespace SpecUtils
00023         {
00024                 template <typename T> class RefBasePtrProxy;
00025                 template <typename T> class RefBasePtrPtrProxy;
00026         }
00027 
00028         /**
00029          * Основная реализация подсчета ссылок. Применяется в качестве базового класса или примеси для пользовательских классов, которые управляются подсчетом ссылок.
00030          * 
00031          * Обеспечивает подсчет кол-ва ссылок и самоуничтожение при их отсутствии. Конструктор устанавливает кол-во ссылок в 0. Деструктор данного класса объевлен виртуальным, что обеспечивает вызовы деструкторов производных классов.
00032          * 
00033          * Данный класс следует использовать когда в деструкторе не требуется работа с ссылочными указателями на данный объект (она невозможна, т.к. при выполнении деструктора объект уже находится в удаляемом состоянии). Данный класс подходит для большинства случаев реализации подсчета ссылок.
00034          * 
00035          * Ограничения:
00036          * - в конструкторах производных классов запрещено использовать ссылочные указатели на конструируемый объект.
00037          * - если объект был создан в статической памяти или в стеке, то использование ссылочных указателей с объектом запрещено (это ограничение можно обойти, используя метод RefPtr::SetPointerWithoutRefCounting()).
00038          * 
00039          * Данный класс обеспечивает многопоточность.
00040          * @author Овсеевич Р.
00041          * \ingroup RefCount
00042          */
00043         class RefBase: virtual public IRefObject
00044         {
00045         protected:
00046 
00047         /**
00048          * Конструктор. Устанавливает кол-во ссылок в 0. 
00049          */
00050                 RefBase(): referenceCounter(0) {}
00051 
00052                 /**
00053                  * Виртуальный деструктор. Проверяет кол-во ссылок на уничтожаемый объект.
00054                  * 
00055                  * Исключение: RefObjectUsedException - когда на объект еще имеются ссылки. Это исключение обрабатывается самой библиотекой и служит отладочным целям.
00056                  */
00057                 virtual ~RefBase()
00058                 {
00059                         // Если при уничтожении объекта на него еще сохраняются ссылки, то
00060                         // возбуждаем спец. исключение для информирования об этом, которое
00061                         // сами же и перехватываем (деструктор не должен использ. исключения).
00062                         if (!IsDeleteState())
00063                         {
00064                                 try
00065                                 {
00066                                         if (referenceCounter > 0 or referenceCounter < -1)
00067                                                 throw RefObjectUsedException("Cntm::RefBase::~RefBase");
00068                                 }
00069                                 catch (...)
00070                                 {                               
00071                                 }
00072                         }
00073                 }
00074 
00075         /**
00076          * Реализация IRefObject::DeleteInstance.
00077          * 
00078          * Уничтожает объект. 
00079          */
00080                 void DeleteInstance() 
00081                 { 
00082                         delete this;
00083                 }
00084         
00085         private:
00086 
00087                 friend class RefBaseEx;
00088                 template <typename T> friend class SpecUtils::RefBasePtrProxy;
00089                 template <typename T> friend class SpecUtils::RefBasePtrPtrProxy;
00090 
00091                 /**
00092                  * Счетчик ссылок.
00093                  */
00094                 int referenceCounter;
00095 
00096         /**
00097                  * Реализация IRefObject::IncRefCount. Метод синхронизирован критической секцией подсчета ссылок.
00098                  * 
00099                  * Увеличить кол-во ссылок. Возвращает true, если объект не находится в удаляемом состоянии и кол-во ссылок увеличено, иначе возвращается false.
00100          */
00101                 bool IncRefCount() { return IncRefCountImpl(); }
00102 
00103         /**
00104          * Реализация IRefObject::DecRefCount. Метод синхронизирован критической секцией подсчета ссылок.
00105          * 
00106          * Уменьшить кол-во ссылок. Если счетчик ссылок достиг 0, то возвращается true, иначе возвращается false.
00107          */
00108                 bool DecRefCount() { return DecRefCountImpl(); }
00109 
00110         /**
00111          * Специальная инлайн реализация увеличения кол-ва ссылок для оптимизации. Вызывается из IRefObject::IncRefCount. Метод синхронизирован критической секцией подсчета ссылок.
00112          * 
00113          * Увеличить кол-во ссылок. Возвращает true, если объект не находится в удаляемом состоянии и кол-во ссылок увеличено, иначе возвращается false.
00114          */
00115                 bool IncRefCountImpl() 
00116                 { 
00117                         // Т.к. изменения счетчика ссылок защищены глобальной критической секцией,
00118                         // то изменения счетчика можно выполнять в несколько действий.
00119                         if (++referenceCounter == 0)
00120                         {
00121                                 // Объект был в удаляемом состоянии, возвращаем его туда обратно.
00122                                 referenceCounter = -1;
00123                                 return false;
00124                         }
00125                         return true;
00126                 }
00127                 
00128         /**
00129          * Специальная инлайн реализация уменьшения кол-ва ссылок для оптимизации. Вызывается из IRefObject::DecRefCount. Метод синхронизирован критической секцией подсчета ссылок.
00130          * 
00131          * Уменьшить кол-во ссылок. Если счетчик ссылок достиг 0, то возвращается true, иначе возвращается false.
00132          */
00133                 bool DecRefCountImpl() 
00134                 {
00135                         // Т.к. изменения счетчика ссылок защищены глобальной критической секцией,
00136                         // то изменения счетчика можно выполнять в несколько действий.
00137                         if (--referenceCounter == 0)
00138                         {
00139                                 // Ссылок больше нет, переходим в удаляемое состояние.
00140                                 referenceCounter = -1;
00141                                 return true;
00142                         }
00143                         return false; 
00144                 }
00145                 
00146         /**
00147          * Возвращает true, если объект в удаляемом состоянии.
00148          */
00149                 bool IsDeleteState() { return referenceCounter == -1; }
00150 
00151         /**
00152          * Установить счетчик ссылок в начальное значение, при условии, что
00153          * объект находится в удаляемом состоянии.
00154          */
00155                 void ReinitReferenceCounter()
00156                 {
00157                         SpecUtils::RefObjectImplUtils::CheckAndSetIntValue(
00158                                 &referenceCounter, -1, 0);
00159                 }
00160         };
00161 
00162 }
00163 
00164 #include <Cntm/RefCount/Internal/RefBaseOpsImpl.h>
00165 
00166 #endif //CNTM_REFBASE_H

SourceForge.net Logo
© Овсеевич Р.В. Документация по CntmLib 1.1.4 от 28 May 2008. Создано системой  doxygen 1.5.3