RefPtr.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_REFPTR_H
00015 #define CNTM_REFPTR_H
00016 #include <cstddef>
00017 #include <typeinfo>
00018 #include <Cntm/Exceptions/IllegalStateException.h>
00019 
00020 namespace Cntm
00021 {
00022 
00023         namespace SpecUtils {}
00024 
00025         /**
00026          * Специальный ссылочный указатель для автоматизации подсчета ссылок на объекты. 
00027          * 
00028          * На данный момент указатель может работать с двумя типами объектов:
00029          * - объектов с полной поддержкой подсчета ссылок, классы которых реализуют интерфейс Cntm::IRefObject;
00030          * - всех прочих типов объектов - для них подсчет ссылок не производится (такая возможность реализована, чтобы была возможность использовать остальные средства библиотеки с объектами без подсчета ссылок).
00031          * 
00032          * Для ссылочных классов, наследующих Cntm::IRefObject, Cntm::RefBase, Cntm::RefBaseEx принцип работы ссылочного указателя следующий: при присвоении указателю ссылки он увеличивает кол-во ссылок на присваиваемый объект и уменьшает на тот объект, на который он ссылался до присвоения.
00033          *
00034          * Пример:
00035          * \code
00036          * // Использование RefPtr(Type* Src). В конструкторе кол-во ссылок устанавливается в 0,
00037          * // при присвоении ссылочному указателю p1 кол-во ссылок увеличивается до 1.
00038          * Class1::Ptr p1 = new Class1(Arg1);
00039          * Class1::Ptr p2 = p1; // Копирование указателя увеличивает кол-во ссылок до 2.
00040          * 
00041          * // Присваивание обычному указатель - кол-во ссылок на новый объект = 0. 
00042          * Class1* c1 = new Class1(Arg3);
00043          * Class1::Ptr p3 = c1; // Кол-во ссылок на второй объект увеличивается до 1.
00044          * // Замена значения указателя увеличивает кол-во ссылок на первый объект до 3, 
00045          * // а на второй - до 0, что приводит к его автоматическому уничтожению.
00046          * p3 = p2; 
00047          * \endcode
00048          * Более полная информация приведена в описании классов Cntm::IRefObject, Cntm::RefBase, Cntm::RefBaseEx.
00049          *
00050          * Данный класс обеспечивает многопоточность.
00051          * @author Овсеевич Р.
00052          * \ingroup RefCount
00053          */
00054         template < typename T >
00055         class RefPtr
00056         {
00057         public:
00058 
00059                 template < typename T2 > friend class RefPtr;
00060 
00061                 typedef T Type;
00062 
00063                 /**
00064                  * Конструктор без параметров. Инициализирует указатель в NULL.
00065                  */
00066                 RefPtr(): pointer(NULL) {CheckCompleteType();}
00067 
00068                 /**
00069                  * Конструктор. Использует указатель на объект. Увеличивает кол-во ссылок на объект, если он не NULL.
00070                  * 
00071                  * Данный конструктор следует использовать при создании объекта с помощью new или при преобразовании "this" в RefPtr. Во всех прочих случаях конструктор должен использоваться с осторожностью.
00072                  */
00073                 RefPtr(const Type* Src): pointer(NULL)
00074                 {
00075                         using namespace SpecUtils;
00076                         CheckCompleteType();
00077                         RefPtrInitFromRefPtr(pointer,
00078                                 GetRefPtrProxy(Src, const_cast<Type*>(Src)),
00079                                 GetRefPtrPtrProxy(pointer, &pointer));
00080                 }
00081 
00082                 /**
00083                  * Конструктор копирования. Использует ссылочный указатель на объект. Увеличивает кол-во ссылок на объект, если он не NULL.
00084                  */
00085                 RefPtr(const RefPtr < Type > & Src): pointer(NULL)
00086                 {
00087                         using namespace SpecUtils;
00088                         CheckCompleteType();
00089                         RefPtrInitFromRefPtr(pointer,
00090                                 GetRefPtrPtrProxy(Src.pointer, const_cast<Type**>(&Src.pointer)),
00091                                 GetRefPtrPtrProxy(pointer, &pointer));
00092                 }
00093 
00094                 /**
00095                  * Конструктор копирования. Использует ссылочный указатель на объект совместимого типа. Увеличивает кол-во ссылок на объект, если он не NULL.
00096                  */
00097                 template < typename T2 >
00098                 RefPtr(const RefPtr < T2 > & Src): pointer(NULL)
00099                 {
00100                         using namespace SpecUtils;
00101                         CheckCompleteType();
00102                         CheckCast(Src.Pointer());
00103                         RefPtrInitFromRefPtr(pointer,
00104                                 GetRefPtrPtrProxy(Src.pointer, const_cast<T2**>(&Src.pointer)),
00105                                 GetRefPtrPtrProxy(pointer, &pointer));
00106                 }
00107 
00108                 /**
00109                  * Деструктор. Уменьшает кол-во ссылок на объект, если он не NULL.
00110                  */
00111                 ~RefPtr()
00112                 {
00113                         using namespace SpecUtils;
00114                         CheckCompleteType();
00115                         RefPtrDeinitPtr(pointer, GetRefPtrPtrProxy(pointer, &pointer));
00116                 }
00117 
00118                 /**
00119                  * Оператор присвоения. Использует указатель на объект. Увеличивает кол-во ссылок на новый объект и уменьшает на старый, если они не NULL.
00120                  * 
00121                  * Данный оператор следует использовать при создании объекта с помощью new или при преобразовании "this" в RefPtr. Во всех прочих случаях оператор должен использоваться с осторожностью.
00122                  */
00123                 RefPtr < Type > & operator = (const Type* Src)
00124                 {
00125                         using namespace SpecUtils;
00126                         CheckCompleteType();
00127                         RefPtrChangeFromRefPtr(pointer,
00128                                 GetRefPtrProxy(Src, const_cast<Type*>(Src)),
00129                                 GetRefPtrPtrProxy(pointer, &pointer));
00130                         return *this;
00131                 }
00132 
00133                 /**
00134                  * Оператор присвоения. Использует ссылочный указатель на объект совместимого типа. Увеличивает кол-во ссылок на новый объект и уменьшает на старый, если они не NULL.
00135                  */
00136                 template < typename T2 >
00137                 RefPtr < Type > & operator = (const RefPtr < T2 > & Src)
00138                 {
00139                         using namespace SpecUtils;
00140                         CheckCompleteType();
00141                         CheckCast(Src.Pointer());
00142                         RefPtrChangeFromRefPtr(pointer,
00143                                 GetRefPtrPtrProxy(Src.pointer, const_cast<T2**>(&Src.pointer)),
00144                                 GetRefPtrPtrProxy(pointer, &pointer));
00145                         return *this;
00146                 }
00147 
00148                 /**
00149                  * Оператор присвоения. Использует ссылочный указатель на объект. Увеличивает кол-во ссылок на новый объект и уменьшает на старый, если они не NULL.
00150                  */
00151                 RefPtr < Type > & operator = (const RefPtr < Type > & Src)
00152                 {
00153                         using namespace SpecUtils;
00154                         CheckCompleteType();
00155                         RefPtrChangeFromRefPtr(pointer,
00156                                 GetRefPtrPtrProxy(Src.pointer, const_cast<Type**>(&Src.pointer)),
00157                                 GetRefPtrPtrProxy(pointer, &pointer));
00158                         return *this;
00159                 }
00160 
00161                 /**
00162                  * Оператор разыменования, возвращает ссылку на объект.
00163                  */
00164                 Type& operator* () const
00165                 {
00166                         CheckCompleteType();
00167                         Type* tmp = pointer;
00168 #ifndef CNTM_NO_DEREFERENCE_CHECK
00169                         if (!tmp) throw IllegalStateException(std::string("Разыменование указателя на объект Cntm::RefPtr{") + typeid(Type).name() + "}::operator*()", "Ссылочный указатель не указывает на объект, использование ссылок на NULL запрещено");
00170 #endif //CNTM_NO_DEREFERENCE_CHECK
00171                         return *tmp;
00172                 }
00173 
00174                 /**
00175                  * Оператор доступа к членам.
00176                  */
00177                 Type* operator-> () const
00178                 {
00179                         CheckCompleteType();
00180                         Type* tmp = pointer;
00181 #ifndef CNTM_NO_DEREFERENCE_CHECK
00182                         if (!tmp) throw IllegalStateException(std::string("Доступ к членам объекта Cntm::RefPtr{") + typeid(Type).name() + "}::operator->()", "Ссылочный указатель не указывает на объект, доступ к членам объекта невозможен");
00183 #endif //CNTM_NO_DEREFERENCE_CHECK
00184                         return tmp;
00185                 }
00186 
00187                 /**
00188                  * Оператор преобразования к указателю.
00189                  */
00190                 operator Type* () const
00191                 {
00192                         CheckCompleteType();
00193                         return pointer;
00194                 }
00195 
00196                 /**
00197                  * Приведение к типу bool.
00198                  */
00199                 operator bool () const
00200                 {
00201                         CheckCompleteType(); 
00202                         return pointer != NULL;
00203                 }
00204 
00205                 /**
00206                  * Оператор not.
00207                  */
00208                 bool operator ! () const
00209                 {
00210                         CheckCompleteType(); 
00211                         return pointer == NULL;
00212                 }
00213 
00214                 /**
00215                  * Оператор сравнения на равенство. Использует указатель на объект.
00216                  */
00217                 bool operator == (Type* Ptr) const
00218                 {
00219                         CheckCompleteType(); 
00220                         return pointer == Ptr;
00221                 }
00222 
00223                 /**
00224                  * Оператор сравнения на равенство. Использует ссылочный указатель.
00225                  */
00226                 bool operator == (const RefPtr & Ptr) const
00227                 {
00228                         CheckCompleteType();
00229                         return pointer == Ptr.Pointer();
00230                 }
00231 
00232                 /**
00233                  * Оператор сравнения на равенство. Использует ссылочный указатель.
00234                  */
00235                 template < typename T2 >
00236                 bool operator == (const RefPtr < T2 > & Ptr) const
00237                 {
00238                         CheckCompleteType();
00239                         return pointer == Ptr.Pointer();
00240                 }
00241 
00242                 /**
00243                  * Оператор сравнения на неравенство. Использует указатель на объект.
00244                  */
00245                 bool operator != (Type* Ptr) const { CheckCompleteType(); return pointer != Ptr; }
00246 
00247                 /**
00248                  * Оператор сравнения на неравенство. Использует ссылочный указатель.
00249                  */
00250                 bool operator != (const RefPtr & Ptr) const
00251                 {
00252                         CheckCompleteType();
00253                         return pointer != Ptr.Pointer();
00254                 }
00255 
00256                 /**
00257                  * Оператор сравнения на неравенство. Использует ссылочный указатель.
00258                  */
00259                 template < typename T2 >
00260                 bool operator != (const RefPtr < T2 > & Ptr) const
00261                 {
00262                         CheckCompleteType();
00263                         return pointer != Ptr.Pointer();
00264                 }
00265 
00266                 /**
00267                  * Оператор <. Использует ссылочный указатель.
00268                  */
00269                 bool operator < (const RefPtr & Ptr) const
00270                 {
00271                         CheckCompleteType();
00272                         return pointer < Ptr.Pointer();
00273                 }
00274 
00275                 /**
00276                  * Оператор <=. Использует ссылочный указатель.
00277                  */
00278                 bool operator <= (const RefPtr & Ptr) const
00279                 {
00280                         CheckCompleteType();
00281                         return pointer <= Ptr.Pointer();
00282                 }
00283 
00284                 /**
00285                  * Оператор >. Использует ссылочный указатель.
00286                  */
00287                 bool operator > (const RefPtr & Ptr) const
00288                 {
00289                         CheckCompleteType();
00290                         return pointer > Ptr.Pointer();
00291                 }
00292 
00293                 /**
00294                  * Оператор >=. Использует ссылочный указатель.
00295                  */
00296                 bool operator >= (const RefPtr & Ptr) const
00297                 {
00298                         CheckCompleteType();
00299                         return pointer >= Ptr.Pointer();
00300                 }
00301 
00302                 /**
00303                  * Возвращает пустой ссылочный указатель.
00304                  */
00305                 static RefPtr < Type > Null()
00306                 {
00307                         CheckCompleteType();
00308                         return RefPtr();
00309                 }
00310 
00311                 /**
00312                  * Операция статического приведения типов ссылочных указателей. Соответствует static_cast для обычных указателей.
00313                  *
00314                  * Пример: Class1::Ptr p1(new Class1); Class2::Ptr p2 = Class2::Ptr::StaticCast(p1);
00315                  */
00316                 template < typename SrcT >
00317                 static RefPtr < Type > StaticCast(const RefPtr < SrcT > & Src)
00318                 {
00319                         CheckCompleteType();
00320                         RefPtr<SrcT> tmp = Src;
00321                         return RefPtr(static_cast<Type*>(tmp.Pointer()));
00322                 }
00323 
00324                 /**
00325                  * Операция динамического приведения типов ссылочных указателей. Соответствует dynamic_cast для обычных указателей.
00326                  *
00327                  * Пример: Class1::Ptr p1(new Class1); Class2::Ptr p2 = Class2::Ptr::DynamicCast(p1);
00328                  */
00329                 template < typename SrcT >
00330                 static RefPtr < Type > DynamicCast(const RefPtr < SrcT > & Src)
00331                 {
00332                         CheckCompleteType();
00333                         RefPtr<SrcT> tmp = Src;
00334                         return RefPtr(dynamic_cast<Type*>(tmp.Pointer()));
00335                 }
00336 
00337                 /**
00338                  * Получить указатель на объект.
00339                  */
00340                 Type* Pointer() const { return pointer; }
00341 
00342                 /**
00343                  * Проверка на NULL.
00344                  */
00345                 bool IsNull() const { CheckCompleteType(); return pointer == NULL; }
00346 
00347                 /**
00348                  * Возвращает true, если тип Type унаследован от IRefObject, т.е. объект подсчитывает ссылки на себя, false - в противном случае.
00349                  */
00350                 bool IsRefObject()
00351                 {
00352                         using namespace SpecUtils;
00353                         CheckCompleteType();
00354                         return RefPtrIsRefObject(pointer);
00355                 }
00356 
00357                 /**
00358                  * Операция присвоения NULL. Уменьшает кол-во ссылок на старый объект, если он не NULL.
00359                  */
00360                 void SetNull()
00361                 {
00362                         CheckCompleteType();
00363                         SetPointer(NULL);
00364                 }
00365 
00366                 /**
00367                  * Операция присвоения указателя на объект. Увеличивает кол-во ссылок на новый объект и уменьшает на старый, если они не NULL.
00368                  * 
00369                  * Данный метод следует использовать при создании объекта с помощью new или при преобразовании "this" в RefPtr. Во всех прочих случаях метод должен использоваться с осторожностью.
00370                  */
00371                 void SetPointer(Type* Src)
00372                 {
00373                         using namespace SpecUtils;
00374                         CheckCompleteType();
00375                         RefPtrChangeFromRefPtr(pointer,
00376                                 GetRefPtrProxy(Src, Src),
00377                                 GetRefPtrPtrProxy(pointer, &pointer));
00378                 }
00379 
00380                 /**
00381                  * Операция присвоения указателя на объект. Не уменьшает кол-во ссылок на старый объект и не увеличивает кол-во ссылок на новый.
00382                  * 
00383                  * Данный метод может использоваться для перевода объекта на ручное управление ссылками.
00384                  * 
00385                  * Использовать данный метод следует только в случае крайней необходимости, т.к. он нарушает идеологию подсчета сылок.
00386                  */
00387                 void SetPointerWithoutRefCounting(Type* Src)
00388                 {
00389                         using namespace SpecUtils;
00390                         CheckCompleteType();
00391                         RefPtrChangeFromPtrWithoutRefCounting(pointer,
00392                                 GetRefPtrProxy(Src, Src),
00393                                 GetRefPtrPtrProxy(pointer, &pointer));
00394                 }
00395 
00396         private:
00397 
00398                 /**
00399                  * Обычный указатель на объект.
00400                  */
00401                 Type* pointer;
00402 
00403                 /**
00404                  * Метод предназначен для проверки приводимости других типов к типу Type во время компиляции.
00405                  */
00406                 static void CheckCast(Type* Ptr) {}
00407 
00408                 /**
00409                  * Метод предназначен для проверки того, что тип Type полностью определен на момент инстанциации шаблона. Проверка делается для того, чтобы избежать ошибок, когда тип еще не определен, но уже объявлен, т.к. RefPtr работает с типом как с произвольным, потому что на момент инстанциации неизвестно, что тип наследует RefBase.
00410                  */
00411                 static int CheckCompleteType() { return sizeof(Type); }
00412         };
00413 
00414 }
00415 
00416 #endif //CNTM_REFPTR_H
00417 

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