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_EVENTLINKSGROUP_H 00015 #define CNTM_EVENTLINKSGROUP_H 00016 #include <boost/utility.hpp> 00017 #include <boost/thread/recursive_mutex.hpp> 00018 #include <Cntm/Utils/SignatureInfo.h> 00019 #include <Cntm/RefCount/RefPtr.h> 00020 #include <Cntm/Synchro/SynchroSpace.h> 00021 #include <Cntm/Events/DeferEvent.h> 00022 #include <Cntm/Events/DirectEvent.h> 00023 00024 namespace Cntm 00025 { 00026 00027 /** 00028 * Класс группы связей между событием и обработчиком. В качестве события используется либо отложенное либо прямое событие (см. классы Cntm::DeferEvent и Cntm::DirectEvent). Выполняет теже функции, что и обычная связь (см. класс Cntm::EventLink), но может хранить сразу несколько связей. Операция Attach() добавляет новую связь к группе, при этом старые связи сохраняются. Операция Detach() влияет на всю группу, она уничтожает все связи, присутствующие на данный момент в группе. 00029 * 00030 * Данный класс имеет конструктор по умолчанию, создающий пустую связь и конструкторы инициализации, создающие связь указанного события с указанным обработчиком. В деструкторе класса происходит разрушение всех связей, хранящихся в группе. Методы Attach() добавляет новую связь. Метод Detach() разрушает все связи, хранящиеся в группе. Данный класс не имеет конструктора и оператора копирования. 00031 * 00032 * Данный класс является общим для отложенных и прямых событий, и не является шаблоном, т.е. не зависит от сигнатуры события. 00033 * 00034 * Более подробное описание использование класса приведено в описании классов событий (см. классы Cntm::DeferEvent и Cntm::DirectEvent). 00035 * 00036 * Данный класс обеспечивает многопоточность. 00037 * @author Овсеевич Р. 00038 * \ingroup Events 00039 */ 00040 class EventLinksGroup: boost::noncopyable 00041 { 00042 public: 00043 00044 /** 00045 * Конструктор по умолчанию. Создает пустую связь. 00046 */ 00047 EventLinksGroup() {} 00048 00049 /** 00050 * Конструктор инициализации связи. В качестве параметров указывается объект отложенного события, ссылочный указатель на объект обработчика, указатель на метод обработчика, ссылочный указатель на синхропространство (опционально). 00051 * 00052 * Исключения: 00053 * Cntm::NullArgException - если указатель на объект обработчика равен NULL; 00054 * Cntm::IllegalStateException - если не удалось определить синхропространство в котором будет вызван обработчик (явно не задано и не создано главное синхропространство). 00055 * @param Event - ссылка на объект отложенного события, т.е. должен передаваться объект события, с которым происходит связывание. 00056 * @param Object - ссылочный указатель на объект, который будет обрабатывать событие. Если указатель равен NULL, то генерируется исключение Cntm::NullArgException. 00057 * @param Method - указатель на метод обработчика. Сигнатура метода должна полностью совпадать с сигнатурой события, в противном случае будет выдана ошибка компиляции. 00058 * @param Space (опциональный) - синхропространство, в котором будет выполняться обработчик. Если оно явно не указано, то определяется следующим образом. Если объект обработчика является синхрообъектом (см. класс Cntm::SynchroObject), то синхропространство берется из свойства Space() этого объекта. В противном случае используется главное синхропространство (см. Cntm::SynchroSpace::Main()). Если главного синхропространства нет (Cntm::SynchroSpace::Main() возвращает NULL), то генерируется исключение Cntm::IllegalStateException. 00059 */ 00060 template < typename SignatureT, typename ClassT > 00061 EventLinksGroup(DeferEvent < SignatureT > & Event, 00062 RefPtr < ClassT > Object, 00063 typename SignatureInfo < SignatureT > ::template Method < ClassT > ::Pointer Method, 00064 const SynchroSpace::Ptr& Space = SynchroSpace::Ptr()) 00065 { 00066 first = new HandlerStorage(Event.GetHandlersRegister(Object.Pointer(), Space), 00067 HandlerType(Object, reinterpret_cast<typename HandlerType::SignInfo::template Method<ClassT>::Pointer>(Method))); 00068 } 00069 00070 /** 00071 * Конструктор инициализации связи. В качестве параметров указывается объект отложенного события, обычный указатель на объект обработчика, указатель на метод обработчика, ссылочный указатель на синхропространство (опционально). 00072 * 00073 * Исключения: 00074 * Cntm::NullArgException - если указатель на объект обработчика равен NULL; 00075 * Cntm::IllegalStateException - если не удалось определить синхропространство в котором будет вызван обработчик (явно не задано и не создано главное синхропространство). 00076 * @param Event - ссылка на объект отложенного события, т.е. должен передаваться объект события, с которым происходит связывание. 00077 * @param Object - обычный указатель на объект, который будет обрабатывать событие. Если указатель равен NULL, то генерируется исключение Cntm::NullArgException. 00078 * @param Method - указатель на метод обработчика. Сигнатура метода должна полностью совпадать с сигнатурой события, в противном случае будет выдана ошибка компиляции. 00079 * @param Space (опциональный) - синхропространство, в котором будет выполняться обработчик. Если оно явно не указано, то определяется следующим образом. Если объект обработчика является синхрообъектом (см. класс Cntm::SynchroObject), то синхропространство берется из свойства Space() этого объекта. В противном случае используется главное синхропространство (см. Cntm::SynchroSpace::Main()). Если главного синхропространства нет (Cntm::SynchroSpace::Main() возвращает NULL), то генерируется исключение Cntm::IllegalStateException. 00080 */ 00081 template < typename SignatureT, typename ClassT > 00082 EventLinksGroup(DeferEvent < SignatureT > & Event, 00083 ClassT* Object, 00084 typename SignatureInfo < SignatureT > ::template Method < ClassT > ::Pointer Method, 00085 const SynchroSpace::Ptr& Space = SynchroSpace::Ptr()) 00086 { 00087 first = new HandlerStorage(Event.GetHandlersRegister(Object, Space), 00088 HandlerType(Object, reinterpret_cast<typename HandlerType::SignInfo::template Method<ClassT>::Pointer>(Method))); 00089 } 00090 00091 /** 00092 * Конструктор инициализации связи. В качестве параметров указывается объект прямого события, ссылочный указатель на объект обработчика, указатель на метод обработчика. 00093 * 00094 * Исключение Cntm::NullArgException - если указатель на объект обработчика равен NULL. 00095 * @param Event - ссылка на объект прямого события, т.е. должен передаваться объект события, с которым происходит связывание. 00096 * @param Object - ссылочный указатель на объект, который будет обрабатывать событие. Если указатель равен NULL, то генерируется исключение Cntm::NullArgException. 00097 * @param Method - указатель на метод обработчика. Сигнатура метода должна полностью совпадать с сигнатурой события, в противном случае будет выдана ошибка компиляции. 00098 */ 00099 template < typename SignatureT, typename ClassT > 00100 EventLinksGroup(DirectEvent < SignatureT > & Event, 00101 RefPtr < ClassT > Object, 00102 typename SignatureInfo < SignatureT > ::template Method < ClassT > ::Pointer Method) 00103 { 00104 first = new HandlerStorage(Event.GetHandlersRegister(Object.Pointer()), 00105 HandlerType(Object, reinterpret_cast<typename HandlerType::SignInfo::template Method<ClassT>::Pointer>(Method))); 00106 } 00107 00108 /** 00109 * Конструктор инициализации связи. В качестве параметров указывается объект прямого события, обычный указатель на объект обработчика, указатель на метод обработчика. 00110 * 00111 * Исключения: 00112 * Cntm::NullArgException - если указатель на объект обработчика равен NULL; 00113 * @param Event - ссылка на объект прямого события, т.е. должен передаваться объект события, с которым происходит связывание. 00114 * @param Object - обычный указатель на объект, который будет обрабатывать событие. Если указатель равен NULL, то генерируется исключение Cntm::NullArgException. 00115 * @param Method - указатель на метод обработчика. Сигнатура метода должна полностью совпадать с сигнатурой события, в противном случае будет выдана ошибка компиляции. 00116 */ 00117 template < typename SignatureT, typename ClassT > 00118 EventLinksGroup(DirectEvent < SignatureT > & Event, 00119 ClassT* Object, 00120 typename SignatureInfo < SignatureT > ::template Method < ClassT > ::Pointer Method) 00121 { 00122 first = new HandlerStorage(Event.GetHandlersRegister(Object), 00123 HandlerType(Object, reinterpret_cast<typename HandlerType::SignInfo::template Method<ClassT>::Pointer>(Method))); 00124 } 00125 00126 /** 00127 * Добавление новой связи к группе. В качестве параметров указывается объект отложенного события, ссылочный указатель на объект обработчика, указатель на метод обработчика, ссылочный указатель на синхропространство (опционально). 00128 * 00129 * Исключения: 00130 * Cntm::NullArgException - если указатель на объект обработчика равен NULL; 00131 * Cntm::IllegalStateException - если не удалось определить синхропространство в котором будет вызван обработчик (явно не задано и не создано главное синхропространство). 00132 * @param Event - ссылка на объект отложенного события, т.е. должен передаваться объект события, с которым происходит связывание. 00133 * @param Object - ссылочный указатель на объект, который будет обрабатывать событие. Если указатель равен NULL, то генерируется исключение Cntm::NullArgException. 00134 * @param Method - указатель на метод обработчика. Сигнатура метода должна полностью совпадать с сигнатурой события, в противном случае будет выдана ошибка компиляции. 00135 * @param Space (опциональный) - синхропространство, в котором будет выполняться обработчик. Если оно явно не указано, то определяется следующим образом. Если объект обработчика является синхрообъектом (см. класс Cntm::SynchroObject), то синхропространство берется из свойства Space() этого объекта. В противном случае используется главное синхропространство (см. Cntm::SynchroSpace::Main()). Если главного синхропространства нет (Cntm::SynchroSpace::Main() возвращает NULL), то генерируется исключение Cntm::IllegalStateException. 00136 */ 00137 template < typename SignatureT, typename ClassT > 00138 void Attach(DeferEvent < SignatureT > & Event, 00139 RefPtr < ClassT > Object, 00140 typename SignatureInfo < SignatureT > ::template Method < ClassT > ::Pointer Method, 00141 const SynchroSpace::Ptr& Space = SynchroSpace::Ptr()) 00142 { 00143 HandlerStorage* hs = new HandlerStorage(Event.GetHandlersRegister(Object.Pointer(), Space), 00144 HandlerType(Object, reinterpret_cast<typename HandlerType::SignInfo::template Method<ClassT>::Pointer>(Method))); 00145 boost::recursive_mutex::scoped_lock lock(mutex); 00146 hs->SetNextHandler(first); 00147 first = hs; 00148 } 00149 00150 /** 00151 * Добавление новой связи к группе. В качестве параметров указывается объект отложенного события, обычный указатель на объект обработчика, указатель на метод обработчика, ссылочный указатель на синхропространство (опционально). 00152 * 00153 * Исключения: 00154 * Cntm::NullArgException - если указатель на объект обработчика равен NULL; 00155 * Cntm::IllegalStateException - если не удалось определить синхропространство в котором будет вызван обработчик (явно не задано и не создано главное синхропространство). 00156 * @param Event - ссылка на объект отложенного события, т.е. должен передаваться объект события, с которым происходит связывание. 00157 * @param Object - обычный указатель на объект, который будет обрабатывать событие. Если указатель равен NULL, то генерируется исключение Cntm::NullArgException. 00158 * @param Method - указатель на метод обработчика. Сигнатура метода должна полностью совпадать с сигнатурой события, в противном случае будет выдана ошибка компиляции. 00159 * @param Space (опциональный) - синхропространство, в котором будет выполняться обработчик. Если оно явно не указано, то определяется следующим образом. Если объект обработчика является синхрообъектом (см. класс Cntm::SynchroObject), то синхропространство берется из свойства Space() этого объекта. В противном случае используется главное синхропространство (см. Cntm::SynchroSpace::Main()). Если главного синхропространства нет (Cntm::SynchroSpace::Main() возвращает NULL), то генерируется исключение Cntm::IllegalStateException. 00160 */ 00161 template < typename SignatureT, typename ClassT > 00162 void Attach(DeferEvent < SignatureT > & Event, 00163 ClassT* Object, 00164 typename SignatureInfo < SignatureT > ::template Method < ClassT > ::Pointer Method, 00165 const SynchroSpace::Ptr& Space = SynchroSpace::Ptr()) 00166 { 00167 HandlerStorage* hs = new HandlerStorage(Event.GetHandlersRegister(Object, Space), 00168 HandlerType(Object, reinterpret_cast<typename HandlerType::SignInfo::template Method<ClassT>::Pointer>(Method))); 00169 boost::recursive_mutex::scoped_lock lock(mutex); 00170 hs->SetNextHandler(first); 00171 first = hs; 00172 } 00173 00174 /** 00175 * Добавление новой связи к группе. В качестве параметров указывается объект прямого события, ссылочный указатель на объект обработчика, указатель на метод обработчика. 00176 * 00177 * Исключения: 00178 * Cntm::NullArgException - если указатель на объект обработчика равен NULL; 00179 * @param Event - ссылка на объект прямого события, т.е. должен передаваться объект события, с которым происходит связывание. 00180 * @param Object - ссылочный указатель на объект, который будет обрабатывать событие. Если указатель равен NULL, то генерируется исключение Cntm::NullArgException. 00181 * @param Method - указатель на метод обработчика. Сигнатура метода должна полностью совпадать с сигнатурой события, в противном случае будет выдана ошибка компиляции. 00182 */ 00183 template < typename SignatureT, typename ClassT > 00184 void Attach(DirectEvent < SignatureT > & Event, 00185 RefPtr < ClassT > Object, 00186 typename SignatureInfo < SignatureT > ::template Method < ClassT > ::Pointer Method) 00187 { 00188 HandlerStorage* hs = new HandlerStorage(Event.GetHandlersRegister(Object.Pointer()), 00189 HandlerType(Object, reinterpret_cast<typename HandlerType::SignInfo::template Method<ClassT>::Pointer>(Method))); 00190 boost::recursive_mutex::scoped_lock lock(mutex); 00191 hs->SetNextHandler(first); 00192 first = hs; 00193 } 00194 00195 /** 00196 * Добавление новой связи к группе. В качестве параметров указывается объект прямого события, обычный указатель на объект обработчика, указатель на метод обработчика. 00197 * 00198 * Исключения: 00199 * Cntm::NullArgException - если указатель на объект обработчика равен NULL; 00200 * @param Event - ссылка на объект прямого события, т.е. должен передаваться объект события, с которым происходит связывание. 00201 * @param Object - обычный указатель на объект, который будет обрабатывать событие. Если указатель равен NULL, то генерируется исключение Cntm::NullArgException. 00202 * @param Method - указатель на метод обработчика. Сигнатура метода должна полностью совпадать с сигнатурой события, в противном случае будет выдана ошибка компиляции. 00203 */ 00204 template < typename SignatureT, typename ClassT > 00205 void Attach(DirectEvent < SignatureT > & Event, 00206 ClassT* Object, 00207 typename SignatureInfo < SignatureT > ::template Method < ClassT > ::Pointer Method) 00208 { 00209 HandlerStorage* hs = new HandlerStorage(Event.GetHandlersRegister(Object), 00210 HandlerType(Object, reinterpret_cast<typename HandlerType::SignInfo::template Method<ClassT>::Pointer>(Method))); 00211 boost::recursive_mutex::scoped_lock lock(mutex); 00212 hs->SetNextHandler(first); 00213 first = hs; 00214 } 00215 00216 /** 00217 * Разрушить все связи, хранящиеся в группе. 00218 */ 00219 void Detach() 00220 { 00221 boost::recursive_mutex::scoped_lock lock(mutex); 00222 HandlerStorage::Ptr temp = first; 00223 first.SetNull(); 00224 lock.unlock(); 00225 temp.SetNull(); 00226 } 00227 00228 private: 00229 00230 typedef SpecUtils::BasicEvent::HandlerType HandlerType; 00231 typedef SpecUtils::BasicEvent::HandlersRegisterEx HandlersRegister; 00232 00233 /** 00234 * Класс эл-та однонаправленного списка, используемый для хранения связи. Содержит как саму связь, так и ссылочный указатель на следующую связь. 00235 */ 00236 class HandlerStorage: public RefBase 00237 { 00238 public: 00239 00240 /** 00241 * Конструктор. 00242 */ 00243 HandlerStorage(const HandlersRegister::Ptr& Reg, const HandlerType& Value): handler(Reg, Value) {} 00244 00245 /** 00246 * Установить указатель на следующую связь. 00247 */ 00248 void SetNextHandler(const HandlerStorage::Ptr& Next) { next = Next; } 00249 00250 private: 00251 00252 /** 00253 * Эл-т перечня, содержащий информацию об обработчике события. 00254 */ 00255 HandlersRegister::Item handler; 00256 00257 /** 00258 * Ссылочный указатель на следующую связь. 00259 */ 00260 HandlerStorage::Ptr next; 00261 }; 00262 00263 /** 00264 * Глобальная критическая секция для операций с указателем на первую связь, хранящуюся в группе. 00265 */ 00266 static boost::recursive_mutex mutex; 00267 00268 /** 00269 * Ссылочный указатель на первую связь, хранящуюся в группе. Когда происходит добавление новой связи, она получает ссылочный указатель на текущую первую связь, а этому указателю присваивается новое значение. Т.о. строится однонаправленный список текущих связей группы. Когда происходит удаление всех связей в методе Detach() или деструкторе, то указатель на первую связь теряется и начинается цепная реакция уничтожения связей, начиная с последней добавленной. 00270 */ 00271 HandlerStorage::Ptr first; 00272 }; 00273 00274 } 00275 00276 #endif //CNTM_EVENTLINKSGROUP_H
© Овсеевич Р.В. Документация по CntmLib 1.1.4 от 28 May 2008. Создано системой 1.5.3 |