По своей сути синхропространство является критической секцией (мьютексом), синхронизирующей операции объектов, принадлежащих синхропространству (синхрообъектов, классы которых унаследованы от Cntm::Synchro...Base). Для того, чтобы при выполнении операции объекта в многопоточной среде не происходило гонок, такие операции должны выполняться внутри синхропространства, для чего поток выполнения должен войти в синхропространство. В каждый момент времени в синхропространстве может находится только один поток выполнения.
Существует 2 режима входа входа в пространство: реентерабельный и не реентерабельный. Сначала рассмотрим что такое реентерабельный (повторный) вход на примере оконной системы. Пусть у нас есть форма, есть периодический таймер и есть обаботчик сигнала от этого таймера. Пусть в этом обработчике мы отображаем модальное окно сообщения. Тогда если долго его не закрывать сработает таймер и снова будет вызван обработчик. Получится, что второй вызов произошел рекурсивно из той точки обработчика, где произведено отображение диалогового окна. В большинстве случаев это не страшно, однако в сложных системах может приводить к трудноуловимым ошибкам. Рекурсивным может быть вход не только в функцию, но и в объект, например, когда из метода, не закончившего до конца изменять данные, каким-то косвенным образом вызывается другой метод того же объекта, изменяющего те же самые данные, что может привести к ошибке. Для предотвращения таких ошибок следует использовать нереентерабельный режим входа в синхропространство, который блокирует возможность косвенного повторного входа в синхропространство. Конкретные аспекты будут рассмотрены для каждого типа синхропространств отдельно. Использование реентерабельного режима рекомендуется свести к минимуму.
Другое назначение синхропространства - выполнение отложенных синхрозаданий. Использование и выполнение этих заданий выглядит следующим образом. Поток выполнения создает задание и добавляет его в очередь (FIFO) заданий указанного синхропространства (при этом не важно произведен ли вход в указанное синхропространство или нет). После этого механизм синхропространства производит вход в это пространство (как только это будет возможно) в реентерабельном режиме (см. выше) и выполненяет задния из очереди, т.е. выполнение каждого задания начинается в реентерабельном режиме. Если добавление задания в синхропространство производится внутри этого пространства, то гарантируется, что выполнение заданий начнется только после выхода из этого синхропространства, т.е. при добавления заданий реентерабельный вход в пространство невозможен. При реентерабельном входе в синхропространство (например, при отображении модального окна) произойдет выполнение отложенных заданий.
Через механизм отложенных синхрозаданий работают такие компоненты системы как деинициализация синхрообъектов и отложенные события и процедуры.
Синхропространства можно поделить на главные (Cntm::...MainSynchroSpace) и дополнительные (Cntm::ExtraSynchroSpace). В системе может быть только одно главное синхропространство (на всем протяжении работы системы) и несколько дополнительных. Задачи дополнительных синхропространств описаны выше, задачи главного синхропространства несколько шире. К задачам главного синхропространства относится обеспечение жизненного цикла приложения. Под этим подразумевается, что оно запускает цикл обработки сообщений в главном потоке (или использует циклы других систем, например QT). Система работает, пока работает цикл, система переходит к завершению работы, когда произведен выход из цикла (пример: в QT запуск цикла производится методом QApplication::exec() - a.exec(), после выхода из которого система приступает к завершению работы). Важной особенностью главного синхропространства является то, что оно препятствует завершению работы, пока остается хотя бы один синхрообъект или одно синхропространство. Это повышает надежность завершающих операций, одновременно требует более четкой проектировки структуры объектов. Конкретное описание различных типов главных синхропространств см. в описании соответствующих классов Cntm::...MainSynchroSpace.
Замечания для случая нескольких синхропространств. Несколько синхропространств необходимо когда в системе выполняются длительные операции (например работа с пользовательским интерфейсом) и одновременно требуется быстрая реакция на какие-то события. В это случае следует разделить синхропространства на то, в котором будет производится медленная работа с пользовательским интерфейсом и дополнительное, которое будет обрабатывать события, требующие быстрой реакции. Не стоит без необходимости создавать лишние синхропространства. Когда имеется несколько пространств возможен вложенный вход, т.е. сначала произведен вход в одно пространство, а из него - в другое. Т.к. синхропространства по своей сути являются критическими секциями, то возможен случай смертильных объятий, когда один поток выполнения вошел в 1 пространство и ожидает входа во 2, а другой поток выполнения наоборот. Что бы этого избежать следует входить в синхропространства всегда в одном и том же порядке, другими словами, если составить граф, в котором вершинами будут синхропространства, а направленными дугами - порядок входа из одного пространства в другое, то такой граф не должен содержать циклов.
В заключение следует сказать, что методы синхропространства редко используются напрямую, обычно все операции выполняются через синхрообъекты.
Данный класс обеспечивает многопоточность.
См. определение в файле SynchroSpace.h строка 49
Открытые типы | |
typedef RefPtr < SynchroSpace > | Ptr |
Открытые члены | |
SynchroSpace::Ptr | Space () const |
Возвращает ссылочный указатель на себя. | |
bool | IsReentrantMode () const |
Возвращает текущий режим входа в синхропространство. | |
void | Enter (bool ReentrantMode=false) |
Производит вход в синхропространство. | |
bool | TryEnter (bool ReentrantMode=false) |
Производит попытку входа в синхропространство. | |
void | Leave (bool ReentrantMode=false) |
Производит выход из синхропространства. | |
virtual void | AddSynchroTask (TaskBase *Task)=0 |
Добавить новую задачу в конец очереди. | |
Открытые статические члены | |
static Ptr | Main () |
Возвращает ссылочный указатель на объект главного синхропространства или NULL, если оно отсутствует. | |
Защищенные члены | |
virtual | ~SynchroSpace () |
Виртуальный деструктор. | |
virtual void | DoEnter ()=0 |
Выполнить вход в критическую секцию, связанную с синхропространством. | |
virtual bool | DoTryEnter ()=0 |
Выполнить попытку входа в критическую секцию, связанную с синхропространством. | |
virtual void | DoLeave ()=0 |
Выполнить выход из критической секции, связанную с синхропространством. | |
Защищенные статические члены | |
static bool | SetMainSynchroSpaceFactory (IMainSynchroSpaceFactory *Factory) |
Установить фабрику для получения указателя на объект главного синхропространства. | |
static bool | IsMainThread () |
Возвращает true, если метод был вызван из главного потока (потока, который установил фабрику главного синхропространства) и false - в противном случае. | |
Классы | |
class | IMainSynchroSpaceFactory |
Интерфейс для фабрики класса, возвращающей указатель на объект главного синхропространства. Подробнее... | |
class | TaskBase |
Базовый класс синхронной задачи. Подробнее... | |
class | TaskQueue |
Класс очереди задач для синхронного выполнения. Подробнее... |
typedef RefPtr<SynchroSpace> Cntm::SynchroSpace::Ptr |
Переопределяет метод предка Cntm::IBasicSynchro.
Переопределяется в Cntm::ExtraSynchroSpace, Cntm::MainSynchroSpace и Cntm::QTMainSynchroSpace.
См. определение в файле SynchroSpace.h строка 53
virtual Cntm::SynchroSpace::~SynchroSpace | ( | ) | [inline, protected, virtual] |
static Ptr Cntm::SynchroSpace::Main | ( | ) | [inline, static] |
Возвращает ссылочный указатель на объект главного синхропространства или NULL, если оно отсутствует.
См. определение в файле SynchroSpace.h строка 96
Перекрестные ссылки Cntm::SynchroSpace::IMainSynchroSpaceFactory::QueryMainInstance().
SynchroSpace::Ptr Cntm::SynchroSpace::Space | ( | ) | const [inline, virtual] |
Возвращает ссылочный указатель на себя.
Замещает Cntm::IBasicSynchro.
См. определение в файле SynchroSpace.h строка 101
bool Cntm::SynchroSpace::IsReentrantMode | ( | ) | const [virtual] |
Возвращает текущий режим входа в синхропространство.
Возвращает true, если вход во !все! синхропространства, в которых поток выполнения находится в данный момент, был произведен в реентерабельном режиме. Если был хотя бы один вход в нереентерабельном режиме, то возвращается false.
Метод должен вызываться только после входа в синхропространство и в том же потоке, который произвел вход.
Замещает Cntm::IBasicSynchro.
См. определение в файле SynchroSpace.cpp строка 99
Перекрестные ссылки Cntm::SpecUtils::SysThreadLocalInt::Value().
void Cntm::SynchroSpace::Enter | ( | bool | ReentrantMode = false |
) | [virtual] |
Производит вход в синхропространство.
Если синхропространство занято другим потоком, то производит ожидание, пока другой поток не выйдет из синхропространства.
Допустим рекурсивный (повторный) вход из потока выполнения который уже находится в этом синхропространстве (возможно с другим режимом входа).
Более подробное описание режимов входа и случаев, когда вход в синхропространство выполняется из другого синхропространства приведенов в описании класса Cntm::SynchroSpace.
Вместо вызова метода Enter() и парного ему метода Leave() рекомендуется использовать классы Cntm::Sync и Cntm::ReentrantSync, которые обеспечивают более надежный и удобный способ вызова этих методов. Объекты этих классы производят вход в синхропространство от момента их создания до конца блока, в котором они объявлены.
ReentrantMode | - режим входа (реентерабельный или нет). Описание режимов входа приведено в описании класса Cntm::SynchroSpace. |
Замещает Cntm::IBasicSynchro.
См. определение в файле SynchroSpace.cpp строка 104
Перекрестные ссылки DoEnter().
bool Cntm::SynchroSpace::TryEnter | ( | bool | ReentrantMode = false |
) | [virtual] |
Производит попытку входа в синхропространство.
Если синхропространство занято другим потоком, то возвращает false, иначе входит в синхропространство и возвращает true.
Допустим рекурсивный (повторный) вход из потока выполнения который уже находится в этом синхропространстве (возможно с другим режимом входа).
Более подробное описание режимов входа и случаев, когда вход в синхропространство выполняется из другого синхропространства приведенов в описании класса Cntm::SynchroSpace.
Вместо вызова метода TryEnter() и парного ему метода Leave() рекомендуется использовать классы Cntm::TrySync и Cntm::TryReentrantSync, которые обеспечивают более надежный и удобный способ вызова этих методов. Объекты этих классы производят вход в синхропространство от момента их создания до конца блока, в котором они объявлены.
ReentrantMode | - режим входа (реентерабельный или нет). Описание режимов входа приведено в описании класса Cntm::SynchroSpace. |
Замещает Cntm::IBasicSynchro.
См. определение в файле SynchroSpace.cpp строка 110
Перекрестные ссылки DoTryEnter().
void Cntm::SynchroSpace::Leave | ( | bool | ReentrantMode = false |
) | [virtual] |
Производит выход из синхропространства.
Парный метод для Enter() и TryEnter() (когда последний вернул true). Параметр ReentrantMode должен иметь такое же значение, как и у парного ему метода Enter() и TryEnter().
Более подробное описание режимов входа и случаев, когда вход в синхропространство выполняется из другого синхропространства приведенов в описании класса Cntm::SynchroSpace.
ReentrantMode | - режим входа (реентерабельный или нет). Описание режимов входа приведено в описании класса Cntm::SynchroSpace. |
Замещает Cntm::IBasicSynchro.
См. определение в файле SynchroSpace.cpp строка 117
Перекрестные ссылки DoLeave().
virtual void Cntm::SynchroSpace::AddSynchroTask | ( | TaskBase * | Task | ) | [pure virtual] |
Добавить новую задачу в конец очереди.
Объект задачи д.б. создан в динамической памяти. После выполнения задача автоматически будет удалена. Класс объекта задачи д.б. унаследован от Cntm:: SynchroSpace:: TaskBase. Если в процессе добавления задачи возникнет исключение, задача будет автоматически удалена.
Подробнее о синхрозадачах см. описание класса Cntm::SynchroSpace и Cntm::SynchroSpace::TaskBase.
Исключение: NullArgException если не указана задача.
Task | - задача, которую нужно выполнить. Объект задачи д.б. создан в динамической памяти. |
static bool Cntm::SynchroSpace::SetMainSynchroSpaceFactory | ( | IMainSynchroSpaceFactory * | Factory | ) | [inline, static, protected] |
Установить фабрику для получения указателя на объект главного синхропространства.
В системе может быть только одно главное синхропространство, и если оно уже установлено, то возвращается false. Метод должен вызываться из главного потока.
См. определение в файле SynchroSpace.h строка 246
Перекрестные ссылки Cntm::SpecUtils::SysThreadIdentifier::Store().
static bool Cntm::SynchroSpace::IsMainThread | ( | ) | [inline, static, protected] |
Возвращает true, если метод был вызван из главного потока (потока, который установил фабрику главного синхропространства) и false - в противном случае.
См. определение в файле SynchroSpace.h строка 257
Перекрестные ссылки Cntm::SpecUtils::SysThreadIdentifier::Check().
virtual void Cntm::SynchroSpace::DoEnter | ( | ) | [protected, pure virtual] |
Выполнить вход в критическую секцию, связанную с синхропространством.
Замещается в Cntm::ExtraSynchroSpace, Cntm::MainSynchroSpace и Cntm::QTMainSynchroSpace.
virtual bool Cntm::SynchroSpace::DoTryEnter | ( | ) | [protected, pure virtual] |
Выполнить попытку входа в критическую секцию, связанную с синхропространством.
Замещается в Cntm::ExtraSynchroSpace, Cntm::MainSynchroSpace и Cntm::QTMainSynchroSpace.
virtual void Cntm::SynchroSpace::DoLeave | ( | ) | [protected, pure virtual] |
Выполнить выход из критической секции, связанную с синхропространством.
Замещается в Cntm::ExtraSynchroSpace, Cntm::MainSynchroSpace и Cntm::QTMainSynchroSpace.
© Овсеевич Р.В. Документация по CntmLib 1.1.4 от 28 May 2008. Создано системой 1.5.3 |