Чтение онлайн

на главную - закладки

Жанры

Параллельное и распределенное программирование на С++
Шрифт:

Доменный класс Класс, созданный для имитации некоторого элемента в конкретной предметной области; значение класса связано с этой предметной областью

Составной класс Класс, который содержит другие классы; имеет с этими классами отношения типа «целое-часть»

Конкретный класс Класс, реализация которого определена, что позволяет объявлять экземпляры этого класса; он не предполагается для использования в качестве базового класса и не прелусматривает попыток создавать операции общего характера

Каркасный класс Класс (или коллекция классов), который имеет предопределенную структуру и представляет обобщенный характер функционирования

Безусловно, эти типы классов особенно

полезны для проектов, в которых предполагается реализовать параллельность. Дело в том, что они позволяют внедрить принцип компоновки из стандартных блоков. Мы обычно начинаем с примитивных компонентов, используя их для построения классов синхронизации. Классы синхронизации позволят нам создавать контейнерные и каркасные классы, рассчитанные на безопасное внедрение параллелизма. Каркасные классы представляют собой строительные блоки, предназначенные для таких параллельных архитектур более высокого уровня, как мультиагентные системы и «доски объявлений». На каждом уровне сложность параллельного и распределенного программирования уменьшается благодаря использованию различных типов классов, перечисленных в табл. 11.1.

Итак, начнем с интерфейсного класса. Интерфейсный (или адаптерный) класс испоользуется для модификации или усовершенствования интерфейса другого класса или множества классов. Интерфейсный класс может также выступать в качестве оболочки, созданной вокруг одной или нескольких функций, которые не являются членами конкретного класса Такая роль интерфейсного класса позволяет обеспечить обьектно-ориентированный интерфейс с программным обеспечением, которое необязательно является объектно-ориентированным. Более того, интерфейсные классы позволяют упростить интерфейсы таких библиотек функций, как POSIX threads, PVM и MPI. Мы можем «обернуть» необъектно-ориентированную функцию в объектно-ориеитированный интерфейс; либо мы можем «обернуть» в интерфейсный класс некоторые данные, инкапсулировать их и предоставить им таким образом объектно-ориентированный интерфейс. Помимо упрощения сложности некоторых библиотек функций, интерфейсные классы используются для обеспечения разработчиков ПО согласующимся интерфейсом API (Application Programmer Interface). Например, С++-программисты, которые привыкли работать с iostream-классами, получат возможность выполнять операции ввода-вывода, оперируя категориями обьектно-ориентированпых потоков данных. Кривая обучения существенно минимизируется, если новые методы ввода-вывода описать в виде привычного iostream-представлеиия. Например, мы можем представить библиотеку средств передачи сообщений MPI как коллекцию потоков.

mpi_stream Stream1;

mpi_stream Stream2;

Streaml << Messagel << Message2 << Message3;

Stream2 >> Message4;

//. . .

Нри таком подходе программист может целиком сосредоточиться на логике программы и не ломать голову над соблюдением требований к синтаксису библиотеки MPI.

Как воспользоваться преимуществами интерфейсных классов

Зачастую полезно использовать инкапсуляцию, чтобы скрыть детали библиотек функций и обеспечить создание самодостаточных компонентов, которые годятся для многократного использования. Возьмем для примера мьютекс, который мы рассматривали в главе 7. Вспомним, что мьютекс— это переменная специального типа, ис-пользуемая для синхронизации. Мьютексы позволяют получать безопасный доступ к критическом) разделу данных или кода программы. Существует шесть основных функций, предназначенных для работы с переменной типа pthread_mutex_t (POSIX Threads Mutex).

Все эти функции принимают в качестве параметра указатель на переменную типа pthread_mutex_t. Для инкапсуляции доступа к переменной типа pthread_mutex_t и упрощения вызовов функций, которые обращаются к мьютексным переменным, можно использовать интерфейсный класс. Рассмотрим листинг 11.1, в котором объявляется класс mutex.

// Листинг 11.1. Объявление класса mutex

class mutex{ protected:

pthread_mutex_t *Mutex;

pthread_mutexattr_t *Attr; public:

mutex(void)

int lock(void);

int unlock(void);

int trylock(void);

int timedlock(void);

};

Объявив

класс mutex, используем его для определения мьютексных пере м енных. Мы можем объявлять массивы мьютексов и использовать эти пере м енные как члены пользовательских классов. Инкапсулировав пере м енную типа • pthread_mutex_t и мьютексные функции, воспользуемся преимуществами методов объектно-ориентированного программирования. Эти мьютексные переменные можно затем применять в качестве аргументов функций и значений, возвра щ аемых функциями. А поскольку мьютексные функции теперь связаны с переменной типа pthread_mutex_t, то там, где мы используем мьютексную переменную, эти функции также будут доступны.

Функции-члены класса mutex определяются путем заключения в оболочку вызовов соответствующих Pthread-функций, например, так.

// Листинг 11.2. Функции-члены класса mutex

mutex::mutex(void) {

try{

int Value;

Value = pthread_mutexattr_int(Attr); //. . .

Value = pthread_mutex_init(Mutex,Attr); //. . .

\

}

int mutex::lock(void) {

int RetValue;

RetValue = pthread_mutex_lock(Mutex); //. . .

return(ReturnValue);

}

Благодаря инкапсуляции мы также защищаем переменные типа pthread_mutex_t * и pthread_mutexattr_t *. Другими словами, при вызове методов lock, unlock, trylock и других нам не нужно беспокоиться о том, к каким мьютексным переменным или переменным атрибутов будут применены эти функции. Возможность скрывать информацию (посредством инкапсуляции) позволяет программисту писать вполне безопасный код. С помощью свободно распространяемых версий Рthread-функций этим функциям можно передать любую переменную типа pthread_mutex_t. Однако при передаче одной из этих функций неверно заданного мьютекса может возникнуть взаимоблокировка или отсрочка бесконечной длины. Инкапсуляция переменных типа pthread_mutex_t и pthread_mutexattr_t в к л ассе mutex предостав л яет программисту полный контроль над тем, какие функции получат доступ к этим переменным.

Теперь мы можем использовать такой встроенный интерфейсный класс, как mutex, в любых других пользовательских классах, предназначенных для безопасной обработки потоков выполнения. Предположим, мы хотели бы создать очередь с многопоточной поддержкой и многопоточный класс pvm_stream. Очередь будем использовать для хранения поступающих событий для множества потоков, образованных в программе. На некоторые потоки возложена ответственность за отправку сообщений различным PVM-задачам. PVM-задачи и потоки выполняются параллельно. Несколько потоков выполнения разделяют единственный PVM-класс и единственную очередь событий. Отношения между потоками, PVM-задачами, очередью событий и классом pvm_stream показаны на рис. 11.1.

Очередь, показанная на рис. 11.1, представляет собой критический раздел, поскольку она совместно используется несколькими выполняемыми потоками. Класс pvm_stream — это также критический раздел и по той же причине. Если эти критические разделы не синхронизировать и не защитить, то данные в очереди и классе pvm_stream могут разрушиться. Тот факт, что несколько потоков могут одновременно обновлять либо очередь, либо код класса pvm_stream, открывает среду для «гонок». Чтобы не допустить этого, мы должны обеспечить нашу очередь и к л асс pvm_stream встроенны м и средства м и блокировки и разблокировки. Эти средства также поддерживаются классом mutex. На рис. 11.2 показана диаграмма классов для наших пользовательских классов x_queue и pvm_stream.

Поделиться:
Популярные книги

Тройняшки не по плану. Идеальный генофонд

Лесневская Вероника
Роковые подмены
Любовные романы:
современные любовные романы
6.80
рейтинг книги
Тройняшки не по плану. Идеальный генофонд

Барон играет по своим правилам

Ренгач Евгений
5. Закон сильного
Фантастика:
попаданцы
аниме
фэнтези
фантастика: прочее
5.00
рейтинг книги
Барон играет по своим правилам

Завод-3: назад в СССР

Гуров Валерий Александрович
3. Завод
Фантастика:
попаданцы
альтернативная история
5.00
рейтинг книги
Завод-3: назад в СССР

Секретарь лорда Демона

Лунёва Мария
Фантастика:
попаданцы
фэнтези
5.00
рейтинг книги
Секретарь лорда Демона

Отец моего жениха

Салах Алайна
Любовные романы:
современные любовные романы
7.79
рейтинг книги
Отец моего жениха

Идеальный мир для Лекаря 10

Сапфир Олег
10. Лекарь
Фантастика:
юмористическое фэнтези
аниме
5.00
рейтинг книги
Идеальный мир для Лекаря 10

Я тебя не отпущу

Коваленко Марья Сергеевна
4. Оголенные чувства
Любовные романы:
современные любовные романы
5.00
рейтинг книги
Я тебя не отпущу

Бастард Императора. Том 7

Орлов Андрей Юрьевич
7. Бастард Императора
Фантастика:
городское фэнтези
попаданцы
аниме
фэнтези
5.00
рейтинг книги
Бастард Императора. Том 7

Девочка из прошлого

Тоцка Тала
3. Айдаровы
Любовные романы:
современные любовные романы
5.00
рейтинг книги
Девочка из прошлого

Вернуть невесту. Ловушка для попаданки 2

Ардова Алиса
2. Вернуть невесту
Любовные романы:
любовно-фантастические романы
7.88
рейтинг книги
Вернуть невесту. Ловушка для попаданки 2

Идеальный мир для Лекаря 7

Сапфир Олег
7. Лекарь
Фантастика:
юмористическая фантастика
попаданцы
аниме
5.00
рейтинг книги
Идеальный мир для Лекаря 7

Хозяйка дома на холме

Скор Элен
1. Хозяйка своей судьбы
Любовные романы:
любовно-фантастические романы
5.00
рейтинг книги
Хозяйка дома на холме

Жена проклятого некроманта

Рахманова Диана
Фантастика:
фэнтези
6.60
рейтинг книги
Жена проклятого некроманта

Имя нам Легион. Том 9

Дорничев Дмитрий
9. Меж двух миров
Фантастика:
боевая фантастика
рпг
аниме
5.00
рейтинг книги
Имя нам Легион. Том 9