Symbian API. Багатозадачність для бідних з Active Objects. Частина 2.

Якщо розгянути активні об’єкти під мікроскопом, то виявиться що усі вони мають спільного батька – клас CActive. Розглянемо анатомічні особливості пацієнта:

Конструктори

CActive(TInt); Має лише один і він protected. Дозволяє створити активний об”єкт із заданим пріорітетом. Пріоритет визначається внутрішнім типом TPriority, значення важливі на практиці – EPriorityIdle, EPriorityUserInput, EPriorityStandard.

Деструктор

Його завданням є перевірити чи немає активних запитів які ініціював об”єкт. Якщо такі є, тобто об”єкт є насправді активним, він панікує із кодом E32-USER 40. Якщо ж усе нормально, то активний об”єкт видаляється із списку об”єкта розпорядника. Зрозуміло, що деструктори класів похідних він CActive зобов”язані викликати метод Cancel() який призначено саме для скасування поточного активного запиту. Така поведінка спричинена тим, що у C++ знищення об”єкта відбувається таким чином, що спочатку викликається деструктор похідного класу, а вже потім за ним викликається деструктор батька. Тому якщо не викликати метод Cancel(), то можлива помилкова ситуація.

Методи роботи із станом

IsActive(), IsAdded(), Priority(), SetActive(), SetPriority();

Методи роботи із чергою

Deque(); Видаляє об"єкт з черги.

Методи обробки

RunL(), RunError();

Поля

iStatus: TRequestStatus;

У конструкторі CActive() об”єкт обов”язково треба додати до об”єкта-розпорядника потоку. Для цього викликається статичний метод Add(CActive *) класу CActiveScheduler. Об”єкт-розпорядник підтримує двозв”язний список зареєстрованих активних об”єктів погрупованих за пріорітетом. У кожного активного об”єкта має бути принаймні один метод-ініціатор, його завданням є ініціювати перший запит до асинхронного сервісу, передавши у параметр об”єкт TRequestStatus який представляє статус виконання запиту (подібно до IAsyncResult у .NET). Отримавши запит, асинхронний сервіс виставляє значення статусу як KRequestPending. Коли виконання сервісу завершилось він викликає розблоковуючий метод на потоці клієнта.

Алгоритм роботи об”єкта-розпорядника є іншим. Спочатку він заблоковує свій потік виконання. Він прокинеться тільки у разі явного розблокування внаслідок завершення виконання певної асинхронної операції, яку ініціював один з активних об”єктів. Прокинувшись, об”єкт розпорядник знаходить активний об”єкт що його розбудив. Це легко зробити, адже достатньо знайти перший ліпший об”єкт, такий в якого IsActive() == true, та статус відмінний від KRequestPending. При пошуку перевага надається об”єктам із вищим пріорітетом. Знайшовши такий, об”єкт-розпорядник запускає його метод RunL() на виконання. Якщо підчас виконання сталась помилка, то її обробку довіряють методу RunError(), а якщо і він не зумів правильно обробити помилкову ситуацію, то залучають метод Error() об”єкта-розпорядника. Під час обробки операції у методі RunL() можливо і широко практикується повторний виклик асинхронного сервіса. Наприклад, таким чином можна зручно працювати із сервісом системного таймера, мережевим сервісом тощо.

Це була друга стаття на тему використання Active Objects у Symbian API. Наступна розповість детальніше про тип CActiveScheduler та продемонструє невеликий приклад роботи із активним об"єктом.

© 2009 - 2020, Розробка - соціальна ІТ спільнота.
Контакти: info@rozrobka.com
Правила користування