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_MAINSYNCHROSPACE_H 00015 #define CNTM_MAINSYNCHROSPACE_H 00016 #include <boost/thread/recursive_mutex.hpp> 00017 #include <Cntm/Synchro/SynchroSpace.h> 00018 #include <Cntm/SystemUtils/SysCriticalSection.h> 00019 #include <Cntm/SystemUtils/SysSignalFlag.h> 00020 00021 namespace Cntm 00022 { 00023 00024 /** 00025 * Класс главного синхропространства. Описание понятия синхропространства приведено в SynchroSpace. 00026 * 00027 * Для обработки синхронных задач используется главный поток. 00028 * 00029 * Обеспечение жизненного цикла приложения. Для обеспечения жизненного цикла применяется метод Run(). Также в нем реализован цикл обработки синхронных заданий. В общем случае жизненный цикл выглядит следующим образом. 00030 * \code 00031 * int main(args...) 00032 * { 00033 * Cntm::MainSynchroSpace::Begin(); 00034 * ... 00035 * Инициализация 00036 * ... 00037 * Cntm::MainSynchroSpace::Run(); 00038 * ... 00039 * Деинициализация 00040 * ... 00041 * Cntm::MainSynchroSpace::End(); 00042 * return 0; 00043 * } 00044 * \endcode 00045 * 00046 * Метод Begin() производит создание и подготовку главного синхропространства. Далее следует инициализация системы, после чего методом Run() запускается приложение - это и является жизненным циклом приложения. После завершения работы (методом Stop()) происходит деинициализация и выход из главного синхропространства - метод End(). Данный метод производит ожидание момента, когда будут уничтожены все синхрообъекты в системе. В процессе ожидания синхропространство может обрабатывать синхронные задачи. 00047 * 00048 * Замечание. В интервале от метода Begin() до входа в цикл методом Run(), от выхода из цикла до входа в следующий цикл, от выхода из цикла до метода End() главный поток выполнения находится внутри синхропространства. 00049 * 00050 * Существует более простая и удобная структура приложения: 00051 * \code 00052 * int main(args...) 00053 * { 00054 * Cntm::MainSynchroSpace::Application a; 00055 * ... 00056 * Инициализация 00057 * ... 00058 * a.Run(); 00059 * ... 00060 * Деинициализация 00061 * ... 00062 * return 0; 00063 * } 00064 * \endcode 00065 * 00066 * Замечание по реентерабельности. Данный тип синхропространства запрещает реентерабельный вход в синхропространство. Поэтому разница между реентерабельным и не реентерабельным режимами отсутствует. 00067 * @author Овсеевич Р. 00068 * \ingroup Synchro 00069 */ 00070 class MainSynchroSpace : public SynchroSpace 00071 { 00072 public: 00073 00074 typedef RefPtr<MainSynchroSpace> Ptr; 00075 00076 /** 00077 * Класс приложения. Предназначен для автоматизации вызывов MainsynchroSpace::Begin() (вызывается в конструкторе), MainsynchroSpace::End() (вызывается в деструкторе). 00078 * @author Овсеевич Р. 00079 * \ingroup Synchro 00080 */ 00081 class Application 00082 { 00083 public: 00084 00085 /** 00086 * Конструктор. Выполняет операцию Cntm::MainsynchroSpace::Begin(). 00087 */ 00088 Application() : ended(false) 00089 { 00090 MainSynchroSpace::Begin(); 00091 } 00092 00093 /** 00094 * Деструктор. Выполняет операцию Cntm::MainsynchroSpace::End() если ранее не был вызван метод End(). 00095 */ 00096 ~Application() { End(); } 00097 00098 /** 00099 * Запустить жизненный цикл приложения и обработку синхронных заданий. Выполняет операцию Cntm::MainsynchroSpace::Run() 00100 */ 00101 void Run() { MainSynchroSpace::Run(); } 00102 00103 /** 00104 * Метод позволяет выполнить операцию Cntm::MainsynchroSpace::End() до уничтожения объекта приложения. Повторные вызовы данного метода ничего не делают. 00105 */ 00106 void End() 00107 { 00108 if (ended) return; 00109 MainSynchroSpace::End(); 00110 ended = true; 00111 } 00112 00113 private: 00114 00115 /** 00116 * Флаг: был ли уже вызван метод End() или нет. 00117 */ 00118 bool ended; 00119 }; 00120 00121 00122 /** 00123 * Добавить новую задачу в конец очереди. Объект задачи д.б. создан в динамической памяти. После выполнения задача автоматически будет удалена. Класс объекта задачи д.б. унаследован от SynchroSpace::TaskBase. 00124 * 00125 * Подробнее о синхрозадачах см. описание класса SynchroSpace и SynchroSpace::TaskBase. 00126 * 00127 * Система гарантирует, что задача будет выполнена в контексте главного потока синхронно с прочими событиями библиотеки QT. 00128 * 00129 * \throw NullArgException если не указана задача. 00130 * @param Task - задача, которую нужно выполнить. Объект задачи д.б. создан в динамической памяти. 00131 */ 00132 void AddSynchroTask(TaskBase* Task) { implement->AddSynchroTask(Task); } 00133 00134 /** 00135 * Создание и вход в главное синхропространство. Поток, вызвавший этот метод считается главным потоком приложения. 00136 * 00137 * Вместо вызова этого метода рекомендуется использовать класс MainSynchroSpace::Application. 00138 * 00139 * \throw IllegalStateException при попытке повторного создания главного синхропространства (главное синхропространство этого же или другого типа уже создано). 00140 */ 00141 static void Begin(); 00142 00143 /** 00144 * Запустить жизненный цикл приложения и обработку синхронных заданий. Метод будет выполняться до тех пор, пока приложение не будет остановлено методом Stop(). 00145 * 00146 * Данный метод должен вызываться из главного потока приложения. 00147 * 00148 * Допустимо несколько последовательных вызовов данного метода. Поведение при последующих вызовах ничем не отличается от первого вызова. 00149 * 00150 * \throw LoopInNoMainThreadException - при попытке запуска цикла обработки сообщений не из главного потока 00151 * \throw NoReentrantModeException - при попытке реентерабельного входа в синхропространство (рекурсивный вызов данного метода) 00152 */ 00153 static void Run() { implement->Run(); } 00154 00155 /** 00156 * Выход из главного синхропространства. Метод производит ожидание уничтожения всех синхрообъектов и синхропространств. В процессе ожидания запускается цикл обработки событий. 00157 * 00158 * \throw LoopInNoMainThreadException - при попытке завершения работы не из главного потока 00159 */ 00160 static void End() { implement->Finish(); } 00161 00162 /** 00163 * Остановить выполнение приложения. Вызов метода действует на текущий или последующий запуск метода Run(). 00164 */ 00165 static void Stop() { implement->Stop(); } 00166 00167 protected: 00168 00169 friend class Implement; 00170 00171 /** 00172 * Деструктор. 00173 */ 00174 ~MainSynchroSpace() { implement->MainInstanceDeleted(this); } 00175 00176 /** 00177 * Выполнить вход в критическую секцию, связанную с синхропространством. 00178 */ 00179 void DoEnter() { implement->DoEnter(); } 00180 00181 /** 00182 * Выполнить вход в критическую секцию, связанную с синхропространством. 00183 */ 00184 bool DoTryEnter() { return implement->DoTryEnter(); } 00185 00186 /** 00187 * Выполнить вход в критическую секцию, связанную с синхропространством. 00188 */ 00189 void DoLeave() { implement->DoLeave(); } 00190 00191 private: 00192 00193 /** 00194 * Класс, реализующий все функции синхропространства (вход в синхропространство, выполнение синхронных задач), созданием объекта синхропространства и ожидания его уничтожения. 00195 * @author Овсеевич Р. 00196 */ 00197 class Implement: public SynchroSpace::IMainSynchroSpaceFactory 00198 { 00199 public: 00200 00201 /** 00202 * Конструктор. 00203 * 00204 * Исключение: IllegalStateException при попытке повторного создания главного синхропространства. 00205 */ 00206 Implement(); 00207 00208 /** 00209 * Реализация метода Cntm::SynchroSpace::IMainSynchroSpaceFactory::QueryMainInstance. 00210 */ 00211 SynchroSpace::Ptr QueryMainInstance(); 00212 00213 /** 00214 * Выполнение захвата критической секции. 00215 * 00216 * Вызывается из QTMainSynchroSpace::DoEnter(). 00217 */ 00218 void DoEnter() { critSection.Enter(); } 00219 00220 /** 00221 * Выполнение попытки захвата критической секции. 00222 * 00223 * Вызывается из QTMainSynchroSpace::DoTryEnter(). 00224 */ 00225 bool DoTryEnter() { return critSection.TryEnter(); } 00226 00227 /** 00228 * Выполнение выхода из критической секции. 00229 * 00230 * Вызывается из QTMainSynchroSpace::DoLeave(). 00231 */ 00232 void DoLeave() { critSection.Leave(); } 00233 00234 /** 00235 * Добавить новую синхронную задачу. Добавляет задачу в очередь и высталяет сигнальный флаг. 00236 * 00237 * Вызывается из MainSynchroSpace::AddSynchroTask(). 00238 * 00239 * Исключение: NullArgException если не указана задача. 00240 * @param Task - задача, которую нужно выполнить. Объек задачи д.б. создан в динамической памяти. 00241 */ 00242 void AddSynchroTask(SynchroSpace::TaskBase* Task) 00243 { 00244 if (taskQueue.Add(Task)) 00245 signalFlag.Set(); 00246 } 00247 00248 /** 00249 * Метод запуска. Выполняет вход в крит. секцию. 00250 * 00251 * Вызывается из MainSynchroSpace::Begin(). 00252 */ 00253 void Start(); 00254 00255 /** 00256 * Запуск жизненного цикла и обработка синхронных задач. 00257 * 00258 * Вызывается из MainSynchroSpace::Run(). 00259 */ 00260 void Run(); 00261 00262 /** 00263 * Метод ожидает уничтожения всех синхрообъектов (последним уничтожается главное синхропространство). 00264 * 00265 * Вызывается из QTMainSynchroSpace::End(). 00266 */ 00267 void Finish(); 00268 00269 /** 00270 * Остановить выполнение жизненного цикла. 00271 * 00272 * Вызывается из QTMainSynchroSpace::Stop(). 00273 */ 00274 void Stop(); 00275 00276 /** 00277 * Метод сбрасывает указатель на текущее синхропространство. 00278 * 00279 * Вызывается из MainSynchroSpace::~MainSynchroSpace(). 00280 */ 00281 void MainInstanceDeleted(MainSynchroSpace* Inst); 00282 00283 private: 00284 00285 /** 00286 * Критическая секция данного синхропространства. 00287 */ 00288 SpecUtils::SysCriticalSection critSection; 00289 00290 /** 00291 * Сигнальный флаг для пробуждения цикла обработки синхронных задач. 00292 */ 00293 SpecUtils::SysSignalFlag signalFlag; 00294 00295 /** 00296 * Крит. секция, защищающая работу с указателем instance (получение из instance ссылочного указателя, создание нового объекта синхропространства, сброс указателя instance). 00297 */ 00298 boost::recursive_mutex instanceMutex; 00299 00300 /** 00301 * Указатель на синхропространство QT. Инициализируется при создании синхропространства QT и сбрасывается в NULL в деструкторе синхропространства. 00302 */ 00303 SynchroSpace* instance; 00304 00305 /** 00306 * Ссылочный указатель на синхропространство. Инициализируется в конструкторе (в начале выполнения программы) и сбрасывается в методе Finish() (в конце выполнения). 00307 * 00308 * Используется для минимизации созданий объектов синхропространств QT, а также, чтобы избежать преждевременного выхода из цикла обработки событий (если во время работы, когда отображено главное окно будут потеряны ссылки на синхропространство, то произойдет преждевременный выход). 00309 */ 00310 SynchroSpace::Ptr holdInstance; 00311 00312 /** 00313 * Флаг останова. 00314 */ 00315 volatile bool stopping; 00316 00317 /** 00318 * Флаг запущенности. 00319 */ 00320 volatile bool runned; 00321 00322 /** 00323 * Очередь синхронных задач. 00324 */ 00325 TaskQueue taskQueue; 00326 00327 /** 00328 * Произвести обработку синхронных задач из очереди. 00329 */ 00330 void ProcessQueue(); 00331 }; 00332 00333 /** 00334 * Объект, реализующий функции главного синхропространства. 00335 */ 00336 static Implement* implement; 00337 }; 00338 00339 } 00340 00341 #endif //CNTM_MAINSYNCHROSPACE_H
© Овсеевич Р.В. Документация по CntmLib 1.1.4 от 28 May 2008. Создано системой 1.5.3 |