Класс Cntm::ActiveObject
[Cntm.ActiveObjects]

Граф наследования:Cntm::ActiveObject:

Cntm::IRefObject Cntm::ActiveRefBase Cntm::ActiveRefBaseEx Cntm::ActiveSynchroRefBase Cntm::ActiveSynchroRefBaseEx

Полный список членов класса


Подробное описание

Активный объект - это объект, имеющий свои собственные потоки выполнения.

Для того, чтобы создать свой класс активного объекта, его нужно унаследовать от классов Cntm::ActiveRefBase, Cntm::ActiveRefBaseEx, Cntm::ActiveSynchroRefBase или Cntm::ActiveSynchroRefBaseEx (эти объекты добавляют класс Cntm::ActiveObject как примесь к соответствующей реализации подсчета ссылок или реализации синхронизации).

Средства, предоставляемые базовыми классами активных объектов - управление потоками активных объектов (класс Cntm::ActiveThread). Активные объекты могут создавать свои потоки с помощью метода Cntm::ActiveObject::StartThread()() или Cntm::ActiveThread::Start()(). В качестве потока выступает какой-либо метод объекта, которому при запуске можно передать любые аргументы. Потоки активных объектов являются единицами выполнения (класс Cntm::ActiveThread унаследован от Cntm::ExecutionUnit) и взаимодействие с потоками производится через хэндлы потоков (класс Cntm::ActiveThreadHandle), которые возвращаются как результат запуска. Как любая единица выполнения, поток активного объекта м.б. принудительно остановлен, для этого через хэндл ему посылается сигнал останова (процедуры останова подробно описаны в классе Cntm::ExecutionUnit).

Пример:

 class Class1: public ActiveSynchroRefBase
 {
        ActiveThreadHandle hdl;
 
        void Thread1(int a, string s) { ... }
 
        void Start()
        {
                StartThread(&Class1::Thread1)(45, "Text");
                hdl = ActiveThread::Start(this, &Class1::Thread1)(45, "Text");
        }
 };
Активные объекты являются ссылочными объектами. Важной особенностью является то, что при создании потока активного объекта кол-во ссылок на объект не увеличивается. В этом состоит отличие потоков в активных объектах от асинхроных потоковых процедур AsyncProc::Thread()(), т.к. при выполнении асинхронных процедур держится ссылка на объект, поэтому, пока выполняется процедура, объект не может быть уничтожен. Второй важной функцией, которую предоставляет Cntm::ActiveObject, является автоматический останов потоков этого объекта перед уничтожением объекта. Когда на объект не осталось ссылок и он переходит в удаляемое состояние, всем потокам этого объекта автоматически посылается сигнал останова. Гарантируется, что деструктор (а для классов от Cntm::RefBaseEx и метод OnReleaseInstance()) будут вызваны только после завершения всех потоков (или иначе - все потоки (которые являются методами активного объекта) завершатся до вызова деструктора). Т.о. если нужен такой поток выполнения, который бы не блокировал уничтожение ссылочного объекта, а завершался, когда на объект не осталось ссылок, то для этого можно применять активные объекты и их потоки.

Выше говорилось, что поток активного объекта не создает новую ссылку на объект, а также, что поток завершаетмя после перехода объекта в удаляемое состояние (т.е. может выполняться, когда поток находится как в рабочем, так и в удаляемомм состоянии). Если потоку в процессе выполнения требуется ссылочный указатель на свой объект, то он его может получить из обычного, например, из this. При этом следует помнить, что если объект находится в удаляемом состоянии, то преобразование из обычного в ссылочный будет приводить к тому, что ссылочный указатель примет значение NULL.

Для того, чтобы объект при отсутствии на него ссылок смог уничтожиться, все его потоки должны остановиться. Для обнаружения сигнала останова в потоках можно использовать стандартные средства, предлагаемые классом Cntm::ActiveThread - Cntm::ActiveThread::Terminated() и Cntm::ActiveThread::CheckTerminating(). Первый просто возвращает значение флага останова потока, второй проверяет, и если он установлен, то генерирует специальное исключение Cntm::ActiveThreadTerminatingSignal.

Использование Using-объектов. Using-объекты (класс Cntm::Using, пакет Concurrency) - это scoped-объекты, наподобии auto_ptr и т.п., являющиеся по сути ссылочными указателями на активные объекты. Using-объекты преследуют 2 цели: 1 - при создании они проверяют флаг завершения потока и переданный ссылочный указатель на NULL (т.е. объект уже находится в удаляемом состоянии), если какое либо из этих условий истинно, то генерируется специальное исключение Cntm::ActiveThreadTerminatingSignal. 2 цель - хранить полученный ссылочный указатель на всем протяжении времени существования Using-объекта, т.о. гарантируется, что при выполнении кода, находящегося между созданием и деинициализацией Using-объекта активный объект не перейдет в удаляемое состояние. Для синхрообъектов имеются специальные Using-объекты, объединенные с синхросекциями - классы Cntm::UsingSync и Cntm::UsingReentrantSync, которые, кроме всего прочего, производят вход в синхропространство, к которому принадлежит активный синхрообъект. Пример метода активного объекта, выполняющегося в потоке:

 void Thread1(int a, string s)
 {
        while (true) // Бесконечный цикл, в котором выполяниются повторяющиеся операции.
        {
                sleep(1);
                ...
                // Вход в Using-секцию. Либо вход будет успешный, либо, если поток 
                // необходимо завершить, то будет сгенерировано исключение 
                // ActiveThreadTerminatingSignal и произойдет завершение потока, т.к. 
                // оно не перехватывается внутри цикла. 
                Using use(*this);
 
                ... // В этом блоке объект всегда находится не в удаляемом состоянии и 
                        // преобразование обычного указателя (например, this) к ссылочному 
                        // никогда не приведет к результату NULL.
 
                // Выход из блока.
                use.Unuse(); 
                ...
                // Код, специфичный для синхрообъектов.
                // Вход в Using-секцию, в дополнение производится вход в синхропространство.
                UsingSync suse(*this);
                ... // Находимся в синхропространстве. Деинициализация произойдет в деструкторе suse.
        }
 }
В заключение приведем диаграмму, отражающую время жизни потока по отношению к времени жизни объекта:
 Жизнь объекта  - Жизнь потока
 ----------------- Начало создания объекта.
 |              _
 |              |<-Запуск потока.
 |              |
 ----------------- Выход из метода запуска объекта, работа.
 |              |
 |              |
 |              |<-Выполнение потока, когда объект находится в рабочем состоянии (на него есть ссылки).
 |              |
 |              |
 ----------------- Переход объекта в удаляемое состояние (на него не осталось ссылок), потоку сообщается о завершении.
 |              |
 |              |<-Выполнение потока, когда объект находится в удаляемом состоянии.
 |              |  Поток может узнать о завершении статическим методом ActiveThread::Terminated() или конструкцией Using.
 |              |  После того как поток узнает о завершении он должен выполнить процедуру завершения.
 |              |<-Завершающие действия потока, объект находится в удаляемом состоянии.
 |              X
 |
 ----------------- Вызов деструктора или метода OnReleaseInstance когда запущенных потоков не осталось (для синхрообъектов - 
 |                 когда будет возможен вход в синхропространство).
 | 
 |  Выполнение деинициализации объекта.
 X

Замечание по созданию потоков в конструкторе. Создавать потоки в конструкторе активного объекта нельзя, т.к. при создании потока временно создается ссылочный указатель на данный объект. Почему нельзя использовать ссылочные указатели на объект в его конструкторе рассмотрено в разделе "Подсчет ссылок".

Данный класс обеспечивает многопоточность.

Автор:
Овсеевич Р.

См. определение в файле ActiveObject.h строка 169


Открытые типы

typedef RefPtr
< ActiveObject
Ptr

Открытые члены

template<typename MethodSignatureT>
SpecUtils::ActiveThreadFunctor
< typename
SignatureInfo
< MethodSignatureT >
::FuncSign > 
StartThread (MethodSignatureT Method, ActiveThread::ThreadPriority Priority=ActiveThread::tpNormal)
 Запустить поток для данного активного объекта.

Защищенные типы

typedef Register
< SpecUtils::BasicActiveThreadImpl::Ptr
ThreadsRegister

Защищенные члены

 ActiveObject ()
 Конструктор по умолчанию.
virtual ~ActiveObject ()
 Деструктор.
virtual void AllThreadsFinished ()=0
 Служебный виртуальный метод.
void TerminateAllThreads ()
 Сообщить всем потокам об останове и перейти в режим ожидания завершения всех потоков объекта.

Друзья

class SpecUtils::BasicActiveThreadImpl

Определения типов

typedef RefPtr<ActiveObject> Cntm::ActiveObject::Ptr

Переопределяет метод предка Cntm::IRefObject.

См. определение в файле ActiveObject.h строка 173

typedef Register<SpecUtils::BasicActiveThreadImpl::Ptr> Cntm::ActiveObject::ThreadsRegister [protected]

См. определение в файле ActiveObject.h строка 207


Конструктор(ы)

Cntm::ActiveObject::ActiveObject (  )  [inline, protected]

Конструктор по умолчанию.

См. определение в файле ActiveObject.h строка 212

virtual Cntm::ActiveObject::~ActiveObject (  )  [inline, protected, virtual]

Деструктор.

См. определение в файле ActiveObject.h строка 217


Методы

template<typename MethodSignatureT>
SpecUtils::ActiveThreadFunctor< typename SignatureInfo < MethodSignatureT >::FuncSign > Cntm::ActiveObject::StartThread ( MethodSignatureT  Method,
ActiveThread::ThreadPriority  Priority = ActiveThread::tpNormal 
) [inline]

Запустить поток для данного активного объекта.

После вызова метода StartThread() в скобках указываются аргументы, которые следует передать запускаемому в новом потоке методу. Если аргументов нет, ставятся круглые скобки. Если после вызова метода StartThread() не будет второй пары скобок, то поток запущен не будет. Пример:

 StartThread(&Class1::Thread1)(45, "Text");
 StartThread(&Class1::Thread2)();
Метод StartThread(...) олицетворяет идентификатор функции, а вторая пара скобок - его вызов, поэтому когда говорится о методе StartThread()() и подобных ему, то указывается две пары скобок.

Метод StartThread()() возвращает хэндл созданного потока (см. класс Cntm::ActiveThreadHandle).

Исключение: SystemException - системная ошибка при создании нового потока.

Аргументы:
Method - указатель на метод активного объекта, который будет вызван в новом потоке.
Priority - приоритет создаваемого потока.

См. определение в файле ActiveObject.h строка 197

Перекрестные ссылки Cntm::ActiveThread::Start().

virtual void Cntm::ActiveObject::AllThreadsFinished (  )  [protected, pure virtual]

Служебный виртуальный метод.

Вызывается, когда все потоки завершились. В потомках вызывает методы DeleteInstance() классов, реализующих подсчет ссылок.

void Cntm::ActiveObject::TerminateAllThreads (  )  [protected]

Сообщить всем потокам об останове и перейти в режим ожидания завершения всех потоков объекта.

Служебный метод. Когда все потоки будут завершены, вызовется AllThreadsFinished() для дальнейшей деинициализации.

Данный метод вызывается при переходе объекта в удаляемое состояние из метода DeleteInstance().

В промежутке от вызова TerminateAllThreads() до AllThreadsFinished() (состояние ожидания завершения потоков) объект находится в удаляемом состоянии, поэтому создание новых потоков невозможно.

См. определение в файле ActiveObject.cpp строка 16

Перекрестные ссылки Cntm::Register< ValueT, StoreT >::Enumerator::Current(), Cntm::Register< ValueT, StoreT >::GetEnumerator() и Cntm::Register< ValueT, StoreT >::Enumerator::Next().


Документация по друзьям класса и функциям, отноносящимся к классу

friend class SpecUtils::BasicActiveThreadImpl [friend]

См. определение в файле ActiveObject.h строка 243


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