QTMainSynchroSpace.cpp

См. документацию.
00001 /*
00002  * CntmLib - Подсчет ссылок, потоки, синхронизация, асинхронные процедуры, события
00003  * Copyright (c) 2005, Овсеевич Роман, CntmLib@mail.ru
00004  * _______________________________________________________________________________
00005  * Разрешено свободное использование, копирование, распространение, изменение
00006  * (изменение сведений об авторских правах запрещено). Запрещена продажа и 
00007  * включение всей библиотеки или ее частей в другие библиотеки. В сведениях об
00008  * авторских правах на программу (или сведениях о программе, об авторах, 
00009  * использованных средствах разработки и т.д.) должна быть указана информация
00010  * о библиотеке CntmLib, ее авторе и, возможно, сайте или email'е.
00011  * Библиотека поставляется "как есть", без каких-либо гарантий со стороны автора.
00012  */ 
00013 
00014 #ifdef CNTM_USE_QT_SS
00015 
00016 #include <iostream>
00017 #include <Cntm/Synchro/QTMainSynchroSpace.h>
00018 #include <Cntm/Synchro/LoopInNoMainThreadException.h>
00019 #include <Cntm/Synchro/NoReentrantModeException.h>
00020 
00021 // EventLoop //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
00022 
00023 bool Cntm::QTMainSynchroSpace::EventLoop::created = false;
00024 
00025 int Cntm::QTMainSynchroSpace::EventLoop::enterLoop()
00026 {
00027 /*DebugOut*///  std::cerr << "Before enterLoop " << loopLevel() << std::endl;
00028         implement->ReentrantEnter(loopLevel());
00029         int res = QEventLoop::enterLoop();
00030         implement->ReentrantLeave(loopLevel());
00031 /*DebugOut*///  std::cerr << "After enterLoop " << loopLevel() << std::endl;
00032         return res;
00033 }
00034 
00035 
00036 // Implement //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
00037 
00038 Cntm::QTMainSynchroSpace::Implement::Implement(): instance(NULL)
00039 {
00040         if (!SynchroSpace::SetMainSynchroSpaceFactory(this))
00041                 throw IllegalStateException("Cntm::QTMainSynchroSpace::Prepare", "Попытка повторного создания главного синхропространства");
00042         holdInstance = SynchroSpace::Main(); // Получаем свою собственную ссылку на главное синхропространство.
00043 }
00044 
00045 bool Cntm::QTMainSynchroSpace::Implement::event(QEvent* e)
00046 {
00047         switch (e->type())
00048         {
00049                 case QEvent::User + 0:
00050                         taskQueue.Exec();
00051                         return true;
00052                         
00053                 case QEvent::User + 1:
00054                         QApplication::exit(0); 
00055                         return true;
00056                         
00057                 default:
00058                         return false;
00059         }
00060 }
00061 
00062 Cntm::SynchroSpace::Ptr Cntm::QTMainSynchroSpace::Implement::QueryMainInstance()
00063 {
00064         // Сначала пытаемся воспользоваться указателем, который храним на время работы.
00065         SynchroSpace::Ptr res = holdInstance;
00066         if (res) return res;
00067 
00068         // Инициализируем ссылочный указатель из обычного. Если объект не существует
00069         // или он находится в состоянии удаления, то создаем новый объект.
00070         boost::recursive_mutex::scoped_lock lock(instanceMutex);
00071         res.SetPointer(instance);
00072         if (!res)
00073         {
00074                 res = new QTMainSynchroSpace();
00075                 instance = res.Pointer();
00076         }
00077         return res;
00078 }
00079 
00080 void Cntm::QTMainSynchroSpace::Implement::ReentrantEnter(int Level)
00081 {
00082         // Проверка, что реентерабельный вход произведен в главном потоке.
00083         if (!QTMainSynchroSpace::IsMainThread())
00084         {
00085                 std::cerr << "Критическая ошибка: Библиотека QT не позволяет запускать цикл обработки событий не из главного потока." << std::endl;
00086                 throw LoopInNoMainThreadException("Cntm::QTMainSynchroSpace::Implement::ReentrantEnter", "Библиотека QT не позволяет запускать цикл обработки событий не из главного потока");
00087         }
00088 
00089         // Проверка того, что реентерабельный вход вообще разрешен.
00090         SynchroSpace::Ptr space = SynchroSpace::Main();
00091         if (space && !space->IsReentrantMode())
00092         {
00093                 std::cerr << "Критическая ошибка: Запуск цикла обработки событий QT когда вход в главное синхропространство произведен не в REENTRANT режиме." << std::endl;
00094                 throw NoReentrantModeException("Cntm::QTMainSynchroSpace::Implement::ReentrantEnter", "Запуск цикла обработки событий QT когда вход в главное синхропространство произведен не в REENTRANT режиме");
00095         }
00096         
00097         // Посылаем сообщение для выполнения отложенных синхрозадач (т.к. их следует выполнять в цикле обработки сообщений).
00098         QApplication::postEvent(this, new QEvent(QEvent::Type(QEvent::User + 0)));
00099         
00100         // Выходим из критической секции QApplication.
00101         qApp->unlock();
00102 }
00103 
00104 void Cntm::QTMainSynchroSpace::Implement::ReentrantLeave(int Level)
00105 {
00106         // Перед выходом из реентерабельного входа входим в критическую секцию QApplication.
00107         qApp->lock();
00108 }
00109 
00110 void Cntm::QTMainSynchroSpace::Implement::Start()
00111 {
00112         // Входим в синхросекцию QApplication в главном потоке (выйдем перед входом 
00113         // в цикл обработки событий или в конце).
00114         qApp->lock();
00115 }
00116 
00117 void Cntm::QTMainSynchroSpace::Implement::Finish()
00118 {
00119         holdInstance.SetNull(); // Освобождаем свою ссылку на главное синхропространство.
00120         while (instance) qApp->exec(); // Запускаем цикл обработки событий пока остается главное синхропространство.
00121         qApp->unlock(); // Выходим из синхросекции QApplication в главном потоке.
00122 }
00123 
00124 void Cntm::QTMainSynchroSpace::Implement::MainInstanceDeleted(QTMainSynchroSpace* Inst) 
00125 {
00126         // Если синхропространство не было пересоздано когда текущее пространство находилось в удаляемом состоянии,
00127         // сбрасываем указатель и посылаем сообщение о выходе из цикла обработки сообщений. Если пространство было
00128         // пересоздано, то указатель трогать не надо, а о выходе сообщит новое пространство при своем удалении.
00129         boost::recursive_mutex::scoped_lock lock(instanceMutex);
00130         if (instance == Inst)
00131         {
00132                 instance = NULL;
00133                 QApplication::postEvent(this, new QEvent(QEvent::Type(QEvent::User + 1)));
00134         }
00135 }
00136 
00137 
00138 // QTMainSynchroSpace /////////////////////////////////////////////////////////////////////////////////////////////////////////
00139 
00140 Cntm::QTMainSynchroSpace::Implement* Cntm::QTMainSynchroSpace::implement;
00141 
00142 void Cntm::QTMainSynchroSpace::Prepare()
00143 {
00144         EventLoop::CreateEventLoop();
00145         implement = new Implement;
00146 }
00147 
00148 #endif //CNTM_USE_QT_SS

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