Параллельное и распределенное программирование на С++ (Хьюз, Хьюз) - страница 309

>// Листинг 11.25. Определение методов recordMessge() и

>// getMessage() для класса agent_framework

>int agent_framework::recordMessage(void) {

>Mutex.lock();

>BlackBoardStream << Agent[N].message(); Mutex.unlock();

>}

>int agent_framework::getMessage(void) {

>}

>Mutex.lock();

>BlackBoardStream » Values; Agent[N].perceive(Values); Mutex.unlock();

Здесь каркасный класс должен защищать доступ к «классной доске» с помощью объектов синхронизации. Поэтому, когда агенты считывают сообщения с «классной доски» или записывают их туда, синхронизация уже будет обеспечена каркасным классом. Программисту не нужно беспокоиться о синхронизации доступа к «классной доске». Базовая структура агентно-ориентированного каркасного класса agent_framework показана на рис. 11.11.

Рис. 11.11. Базовая структура каркасного класса agent_framework

Обратите внимание на то, что каркасный класс инкапсулирует объектно-ориентированные мьютексы и переменные условий. Агентно-ориентированный каркасный класс (см. рис. 11.11) для организации взаимодействия процессов в MPI- либо PVM-ориентированной системе должен использовать MPI- либо PVM-потоки сообщений. Вспомните, что эти потоки сообщений были разработаны как интерфейсные классы, что позволяет программисту для доступа к PVM- или MPI-классу использовать iostreams-представление. Если MPI- или PVM-классы не используются, агенты могут взаимодействовать через сокеты, каналы или даже общую память. В любом случае мы рекомендуем реализовать примитивы синхронизации с помощью интерфейсных классов, которые упрощают их использование. Структура «классной доски», показанная на рис. 11.11, является объектно-ориентированной и использует преимущества универсальности, обеспечиваемой шаблонными классами, что также упрощает реализацию параллелизма. Агенты, выполняемые параллельно, представляют эффектив-кую модель параллельного и распределенного программирования.

Резюме

Проблемы параллельного программирования, представленные в главе 2, можно эффективно решить, используя «строительные блоки», рассмотренные в этой главе. Роль интерфейсного класса в упрощении использования библиотек функций трудно преувеличить. Интерфейсный класс вносит логичность API-интерфейса путем заключения в оболочку вызовов функций из таких библиотек, как MPI или PVM. Интерфейсные классы обеспечивают типовую безопасность и возможность многократного использования кода, а также позволяют программисту работать в привычной «системе координат», как с PVM- или MPI-потоками данных. Межпроцессное взаимодействие (IPC) упрощается путем связывания канала или потоков сообщений сюБЧгеатБобъектами и перегрузки операторов вставки («) и извлечения (») для пользовательских классов. Класс ostream_iterator доказывает свою полезность в «оптовой» пересылке контейнерных объектов и их содержимого между процессами. Итераторы типа ostream_iterator и istream_iterator также обеспечивают свя-зующее звено между стандартными алгоритмами и IPC-компонентами и методами. Поскольку модель передачи сообщений используется во многих параллельных и распределенных приложениях, то любой метод, который упрощает передачу различных типов данных между процессами, упрощает программирование приложения в целом. К таким способам упрощения относится использование iostreams-классов и итераторов типа ostream_iterator и istream_iterator. Каркасный класс представлен здесь как базовый строительный блок параллельных приложений. Мы рассматриваем классы, подобные классам мьютексов, переменных условий и потоков, как компоненты низкого уровня, которые должны быть скрыты от программиста в каркасном классе (где это возможно!). При создании средне- и крупномасштабных приложений, которые тре-буют реализации параллелизма, программист не должен «застревать» на этих низкоуровневых компонентах. В идеале для удовлетворения требований параллельной обработки каркасный класс должен быть строительным блоком базового уровня и обеспечивать нас «готовыми» схемами равноправных элементов и взаимодействия типа «клиент-сервер». Мы можем использовать различные типы каркасных классов: для обработки чисел, баз данных или применения агентов, технологии «классной доски», GUI и т.д.