SynchroSpace.cpp

См. документацию.
00001 /*
00002  * CntmLib - Подсчет ссылок, потоки, синхронизация, асинхронные процедуры, события
00003  * Copyright (c) 2005, Овсеевич Роман, CntmLib@mail.ru
00004  * _______________________________________________________________________________
00005  * Разрешено свободное использование, копирование, распространение, изменение
00006  * (изменение сведений об авторских правах запрещено). Запрещена продажа и 
00007  * включение всей библиотеки или ее частей в другие библиотеки. В сведениях об
00008  * авторских правах на программу (или сведениях о программе, об авторах, 
00009  * использованных средствах разработки и т.д.) должна быть указана информация
00010  * о библиотеке CntmLib, ее авторе и, возможно, сайте или email'е.
00011  * Библиотека поставляется "как есть", без каких-либо гарантий со стороны автора.
00012  */ 
00013 
00014 #include <Cntm/Exceptions/NullArgException.h>
00015 #include <Cntm/Synchro/SynchroSpace.h>
00016 
00017 // TaskQueue //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
00018 
00019 Cntm::SpecUtils::FastMutex Cntm::SynchroSpace::TaskQueue::mutex;
00020 
00021 bool Cntm::SynchroSpace::TaskQueue::Add(TaskBase* Task)
00022 {
00023         if (!Task) throw NullArgException("Cntm::SynchroSpace::TaskQueue::Add", "Синхрозадача не указана");
00024         
00025         // Добавляем в конец очереди заданий.
00026         try
00027         {
00028                 SpecUtils::FastMutex::Lock lock(mutex);
00029                 Task->InsertBefore(TasksHead());
00030                 bool res = needExec;
00031                 needExec = false;
00032                 return res;
00033         }
00034         catch (...)
00035         {
00036                 delete Task;
00037                 throw;
00038         }
00039 }
00040 
00041 void Cntm::SynchroSpace::TaskQueue::Exec() throw()
00042 {
00043         // Цикл выполнения рекурсивных задач. Если таких задач нет (первый вход в метод Exec()), то
00044         // lastRecurseTask будет указывать на голову списка. Цикл продолжается, пока не будет повторно
00045         // выполнена задача, вызвавшая рекурсию последней.
00046         TaskBase* task = TasksHead();
00047         while (task != lastRecurseTask)
00048         {
00049                 task = NextTask(task); // Получаем без крит. секции, т.к. до lastRecurseTask ничего не меняется.
00050                 try { if (task->IsRecursive()) task->Exec(true); } catch (...) {}
00051         }
00052 
00053         // Переход к следующей после рекурсивной или к первой задаче.
00054         {
00055                 SpecUtils::FastMutex::Lock lock(mutex);
00056                 task = NextTask(task);
00057                 if (task == TasksHead())
00058                 {
00059                         needExec = true;
00060                         return;
00061                 }
00062         }
00063         
00064         // Цикл прохода по заданиям.
00065         TaskBase* oldLastRecurseTask = lastRecurseTask;
00066         while (true)
00067         {
00068                 lastRecurseTask = task;
00069                 try { task->Exec(); } catch (...) {}
00070                 
00071                 {
00072                         SpecUtils::FastMutex::Lock lock(mutex);
00073                         task = NextTask(task);
00074                         lastRecurseTask->Remove();
00075                         if (task == TasksHead())
00076                         {
00077                                 needExec = true;
00078                                 break;
00079                         }
00080                 }
00081 
00082                 try { delete lastRecurseTask; } catch (...) {}
00083         }
00084         try { delete lastRecurseTask; } catch (...) {}
00085         lastRecurseTask = oldLastRecurseTask;
00086 }
00087 
00088 
00089 // SynchroSpace ///////////////////////////////////////////////////////////////////////////////////////////////////////////////
00090 
00091 Cntm::SynchroSpace::IMainSynchroSpaceFactory* Cntm::SynchroSpace::mainFactory = NULL;
00092 
00093 Cntm::SpecUtils::SysThreadIdentifier Cntm::SynchroSpace::mainThreadId;
00094 
00095 Cntm::SpecUtils::SysThreadLocalInt Cntm::SynchroSpace::reentrantCounter;
00096                 
00097 Cntm::SpecUtils::SysThreadLocalInt Cntm::SynchroSpace::noReentrantCounter;
00098 
00099 bool Cntm::SynchroSpace::IsReentrantMode() const
00100 {
00101         return noReentrantCounter.Value() == 0;
00102 }
00103 
00104 void Cntm::SynchroSpace::Enter(bool ReentrantMode)
00105 {
00106         DoEnter();
00107         UpdateCounters(ReentrantMode, +1);
00108 }
00109         
00110 bool Cntm::SynchroSpace::TryEnter(bool ReentrantMode)
00111 {
00112         if (!DoTryEnter()) return false;
00113         UpdateCounters(ReentrantMode, +1);
00114         return true;
00115 }
00116         
00117 void Cntm::SynchroSpace::Leave(bool ReentrantMode)
00118 {
00119         UpdateCounters(ReentrantMode, -1);
00120         DoLeave();
00121 }
00122 
00123 void Cntm::SynchroSpace::UpdateCounters(bool ReentrantMode, int Sign)
00124 {
00125         if (ReentrantMode)
00126                 reentrantCounter.SetValue(reentrantCounter.Value() + Sign);
00127         else
00128                 noReentrantCounter.SetValue(noReentrantCounter.Value() + Sign);
00129 }

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