SyncUtils.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_SYNCUTILS_H
00015 #define CNTM_SYNCUTILS_H
00016 #include <sched.h>
00017 #include <unistd.h>
00018 #include <Cntm/SystemUtils/AtomicUtils.h>
00019 
00020 namespace Cntm
00021 {
00022         namespace SpecUtils
00023         {
00024                 
00025                 /**
00026                  * Класс быстрого нерекурсивного мьютекса. Используется для коротких критических секций.
00027                  * @author Овсеевич Р.
00028                  * \ingroup SystemUtils
00029                  */
00030                 class FastMutex
00031                 {
00032                 public:
00033                         
00034                         /**
00035                          * Класс блокировки для быстрого мьютекса.
00036                          * @author Овсеевич Р.
00037                          */
00038                         class Lock
00039                         {
00040                         public:
00041                                 
00042                                 /**
00043                                  * Конструктор. Захватывает мьютекс.
00044                                  */
00045                                 Lock(FastMutex& Mutex): mutex(&Mutex) { mutex->Enter(); }
00046                                 
00047                                 /**
00048                                  * Конструктор. Захватывает мьютекс.
00049                                  */
00050                                 Lock(FastMutex* Mutex): mutex(Mutex) { mutex->Enter(); }
00051                                 
00052                                 /**
00053                                  * Деструктор. Освобождает мьютекс.
00054                                  */
00055                                 ~Lock() { mutex->Leave(); }
00056                                 
00057                         private:
00058                         
00059                                 /**
00060                                  * Указатель на мьютекс.
00061                                  */
00062                                 FastMutex* mutex;
00063                         };
00064                         
00065                         /**
00066                          * Конструктор.
00067                          */
00068                         FastMutex(): flag(-1) {}
00069                         
00070                         /**
00071                          * Войти в критическую секцию. Если критеческая сеция занята, то производит ожидание ее освобождения. Повторный вызов из того же потока приведет к зависанию.
00072                          */
00073                         void Enter() 
00074                         { 
00075                                 // Пока после увеличения флаг не примет значение 0,
00076                                 // перевести его в предыдущее состояние и ожидать.
00077                                 while (!flag.IncAndTest())
00078                                 {
00079                                         flag.Dec();
00080                                         sched_yield(); 
00081                                 }
00082                         }
00083                         
00084                         /**
00085                          * Выйти из критической секции.
00086                          */
00087                         void Leave() { flag.Dec(); }
00088                         
00089                 private:
00090                         
00091                         /**
00092                          * Флаг занятости критической секции. -1 - свободна, >= 0 - занята.
00093                          */
00094                         AtomicVariable flag;
00095                 };
00096                 
00097                 /**
00098                  * Функция ожидания момента, когда занчение переменной Variable перестанет равняться BadValue.
00099                  * \ingroup SystemUtils
00100                  */
00101                 template < typename T >
00102                 inline void FastWaitNoEqual(volatile const T* Variable, T BadValue)
00103                 {
00104                         while (*Variable == BadValue)
00105                                 sched_yield();
00106                 }
00107 
00108                 /**
00109                  * Функция ожидания момента, когда занчение переменной Variable перестанет равняться Value. В этот момент она атомарно опять устанавливает Value и возвращает то значение, которое было до установки Value.
00110                  * \ingroup SystemUtils
00111                  */
00112                 template < typename T >
00113                 inline T* FastWaitPtrNoEqualAndSet(T*volatile* Variable, T* Value)
00114                 {
00115                         T* res;
00116                         while ((res = AtomicSwapPtr(Variable, Value)) == Value)
00117                                 sched_yield();
00118                         return res;
00119                 }
00120 
00121                 /**
00122                  * Функция ожидания момента, когда занчение переменной Variable станет равной NeedValue.
00123                  * \ingroup SystemUtils
00124                  */
00125                 template < typename T >
00126                 inline void FastWaitEqual(volatile const T* Variable, T NeedValue)
00127                 {
00128                         while (*Variable != NeedValue)
00129                                 sched_yield();
00130                 }
00131 
00132                 /**
00133                  * Функция ожидания момента, когда занчение атомарной переменной станет равной NeedValue.
00134                  * \ingroup SystemUtils
00135                  */
00136                 inline void FastWaitEqual(const AtomicVariable& Variable,
00137                         AtomicVariable::Type NeedValue)
00138                 {
00139                         while (Variable.Value() != NeedValue)
00140                                 sched_yield();
00141                 }
00142 
00143         }
00144 }
00145 
00146 #endif //CNTM_SYNCUTILS_H

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