BasicRefHandle.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_BASICREFHANDLE_H
00015 #define CNTM_BASICREFHANDLE_H
00016 #include <cstddef>
00017 #include <utility>
00018 #include <map>
00019 #include <Cntm/SystemUtils/SysCriticalSection.h>
00020 #include <Cntm/Exceptions/IllegalStateException.h>
00021 #include <Cntm/RefCount/RefPtr.h>
00022 
00023 namespace Cntm
00024 {
00025         namespace SpecUtils
00026         {
00027 
00028                 /**
00029                  * Базовый класс для хэндлов.
00030                  * @author Овсеевич Р. 
00031                  */
00032                 template < typename T, typename RefImplementationT >    
00033                 class BasicRefHandle
00034                 {
00035                 public:
00036                 
00037                         typedef T Type;
00038                         
00039                         /**
00040                          * Оператор доступа к членам.
00041                          */
00042                         Type* operator -> () const
00043                         {
00044                                 Type* tmp = Object().Pointer();
00045 #ifndef CNTM_NO_DEREFERENCE_CHECK
00046                                 if (!tmp) throw IllegalStateException("Доступ к членам объекта Cntm::SpecUtils::BasicRefHadle::operator->()", "Хэндл не связан с объектом, доступ к членам объекта невозможен");
00047 #endif //CNTM_NO_DEREFERENCE_CHECK
00048                                 return tmp;
00049                         }
00050                                 
00051                         /**
00052                          * Оператор преобразования к ссылочному указателю. Возвращает Object().
00053                          */
00054                         operator RefPtr < Type > () const { return Object(); }
00055                                         
00056                         /**
00057                          * Приведение к типу bool. Возвращает Assigned().
00058                          */
00059                         operator bool () const { return Assigned(); }
00060                         
00061                         /**
00062                          * Оператор not. Возвращает !Assigned().
00063                          */
00064                         bool operator ! () const { return !Assigned(); }
00065                         
00066                         /**
00067                          * Оператор сравнения на равенство. Использует ссылочный указатель.
00068                          */
00069                         template < typename T2 >
00070                         bool operator == (const RefPtr < T2 > & Ptr) const { return Object() == Ptr; }
00071         
00072                         /**
00073                          * Оператор сравнения на равенство. Использует хэндл.
00074                          */
00075                         bool operator == (const BasicRefHandle < T, RefImplementationT > & Handle) const
00076                         {
00077                                 return Object() == Handle.Object();
00078                         }
00079                         
00080                         /**
00081                          * Оператор сравнения на неравенство. Использует ссылочный указатель.
00082                          */
00083                         template < typename T2 >
00084                         bool operator != (const RefPtr < T2 > & Ptr) const { return Object() != Ptr; }
00085                         
00086                         /**
00087                          * Оператор сравнения на неравенство. Использует хэндл.
00088                          */
00089                         bool operator != (const BasicRefHandle < T, RefImplementationT > & Handle) const
00090                         {
00091                                 return Object() != Handle.Object();
00092                         }
00093                         
00094                         /**
00095                          * Получить ссылочный указатель на объект, с которым связан хэндл. Если хэндл не связан, то возвращается NULL. 
00096                          */
00097                         RefPtr<T> Object() const 
00098                         {
00099                                 typename Controller::Ptr tmp = controller;
00100                                 return tmp? tmp->HandledObject() : RefPtr<T>::Null();
00101                         }
00102         
00103                         /**
00104                          * Возвращает true, если хэндл связан с объектом и false в противном случае. 
00105                          */
00106                         bool Assigned() const { return controller; }
00107                         
00108                 protected:
00109                 
00110                         /**
00111                          * Конструктор. Инициализирует контроллер. 
00112                          */
00113                         BasicRefHandle(const RefPtr<T>& HandledObject, void (*FinalizeProc)(RefPtr<T>)):
00114                                 controller(Controller::Query(HandledObject, FinalizeProc)) {}
00115                         
00116                         /**
00117                          * Изменить значение. заменяет контроллер для нового объекта. 
00118                          */
00119                         void Assign(const RefPtr<T>& HandledObject, void (*FinalizeProc)(RefPtr<T>))
00120                         {
00121                                 controller = Controller::Query(HandledObject, FinalizeProc);
00122                         }
00123                         
00124                 private:
00125         
00126                         /**
00127                          * Класс контроллера. Обеспечивает при своем уничтожении вызов метода объекта.
00128                          * 
00129                          * Хэндл содержит указатель на контроллер. Когда хэндлов не осталось, контроллер уничтожается.
00130                          * 
00131                          * Контроллеры ведут список объектов и контроллеров в виде map. При инициализации хэндла просматривается список, если для этого объекта уже есть контроллер, то используется он, иначе создается новый. Особый случай, когда контроллер в удаляемом состоянии. В этом случае ему посылается сигнал, что бы он не выполнял вызов метода и не удалял себя из map, а в map для этого объекта помещается новый контроллер. 
00132                          * @author Овсеевич Р.
00133                          */
00134                         class Controller: public RefImplementationT
00135                         {
00136                         private:
00137         
00138                                 typedef std::map<T*, Controller*> Map;
00139         
00140                                 typedef typename std::map<T*, Controller*>::iterator Iterator;
00141         
00142                         public:
00143                                 
00144                                 typedef RefPtr<Controller> Ptr;
00145                                 
00146                                 /**
00147                                  * Возвращает связанный с контроллером объект, для которого будет вызван метод.
00148                                  */
00149                                 RefPtr<T> HandledObject() const { return handledObject; }
00150                                 
00151                                 /**
00152                                  * Возвращает контроллер по указанному объекту. Либо создает его, либо использует существующий.
00153                                  */
00154                                 static Ptr Query(const RefPtr<T>& HandledObject, void (*FinalizeProc)(RefPtr<T>))
00155                                 {
00156                                         if (!HandledObject) return Ptr::Null();
00157                                         
00158                                         SysCriticalSection::Lock lck(critSection);
00159         
00160                                         // Производим попытку вставки нового значения. В любом случае нам вернется 
00161                                         // итератор нового или уже существующего значения в res.first, а в res.second -
00162                                         // true - не было, вставили, false - было.
00163                                         std::pair<Iterator, bool> insres = controllers.insert(std::make_pair(HandledObject.Pointer(), (Controller*)NULL));
00164                                         Iterator it = insres.first;
00165                                         
00166                                         // Если в списке не было контроллера для указанного объекта, то создаем и выходим.
00167                                         if (insres.second) return Ptr(it->second = new Controller(HandledObject, FinalizeProc, it));
00168                                         
00169                                         // Контроллер уже существует и если он не в удаляемом состоянии, то используем его.
00170                                         Ptr res = it->second;
00171                                         if (res) return res;
00172                                         
00173                                         // Контроллер в удаляемом состоянии, поэтому сообщаем старому контроллеру о том, чтобы он
00174                                         // не изымал из перечня свой эл-т, т.к. он будет занят новым контроллером.
00175                                         it->second->recreated = true;
00176                                         return Ptr(it->second = new Controller(HandledObject, FinalizeProc, it));
00177                                 }
00178                                 
00179                         private:
00180                                 
00181                                 /**
00182                                  * Критическая секция, которой блокируются операции со списком объектов.
00183                                  */
00184                                 static SysCriticalSection critSection;
00185                                 
00186                                 /**
00187                                  * Ассоциативный список объектов и их контроллеров.
00188                                  */
00189                                 static Map controllers;
00190                                 
00191                                 /**
00192                                  * Объект, которым управляет контроллер.
00193                                  */
00194                                 RefPtr<T> handledObject;
00195                                 
00196                                 /**
00197                                  * Функция, которую следует вызвать при завершении.
00198                                  */
00199                                 void (*finalizeProc)(RefPtr<T>);                        
00200         
00201                                 /**
00202                                  * Итератор в ассоциативном списке объектов и их контроллеров, соответствующий данному контроллеру.
00203                                  */
00204                                 Iterator iterator;
00205                                 
00206                                 /**
00207                                  * Признак того, что когда контроллер находился в удаляемом состоянии был создан новый хэндл и операции по уничтожению выполнять не надо.
00208                                  */
00209                                 bool recreated;
00210                                 
00211                                 /**
00212                                  * Конструктор.
00213                                  */
00214                                 Controller(const RefPtr<T>& HandledObject, void (*FinalizeProc)(RefPtr<T>), Iterator Iter):
00215                                         RefImplementationT(HandledObject), handledObject(HandledObject), finalizeProc(FinalizeProc), iterator(Iter), recreated(false) {}
00216         
00217                                 /**
00218                                  * Деструктор. Изымает контроллер из списка и вызывает указанный метод. Для синхрохэндлов этот деструктор вызывается синхронизированно отложенно.
00219                                  */
00220                                 ~Controller()
00221                                 {
00222                                         try
00223                                         {
00224                                                 SysCriticalSection::Lock lck(critSection);
00225         
00226                                                 // Если был создан новый контроллер, когда этот находился в удаляемом состоянии, то 
00227                                                 // эл-т списка контроллеров будет занят новым, и финализацию произведет тоже новый.
00228                                                 if (recreated) return;
00229                                         
00230                                                 controllers.erase(iterator);
00231                                                 lck.Unlock();
00232         
00233                                                 finalizeProc(handledObject);
00234                                         }
00235                                         catch (...) {}
00236                                 }
00237                         };
00238         
00239                         /**
00240                          * Контроллер вызова метода. 
00241                          */
00242                         typename Controller::Ptr controller;
00243                 };
00244 
00245         }
00246 }
00247 
00248 template < typename T, typename RefImplementationT >    
00249 Cntm::SpecUtils::SysCriticalSection 
00250         Cntm::SpecUtils::BasicRefHandle < T, RefImplementationT > ::Controller::critSection;
00251 
00252 template < typename T, typename RefImplementationT >    
00253 typename Cntm::SpecUtils::BasicRefHandle < T, RefImplementationT > ::Controller::Map 
00254         Cntm::SpecUtils::BasicRefHandle < T, RefImplementationT > ::Controller::controllers;
00255 
00256 #endif //CNTM_BASICREFHANDLE_H

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