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
© Овсеевич Р.В. Документация по CntmLib 1.1.4 от 28 May 2008. Создано системой 1.5.3 |