MainSynchroSpace.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_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

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