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 }
© Овсеевич Р.В. Документация по CntmLib 1.1.4 от 28 May 2008. Создано системой 1.5.3 |