Пользовательские классы, создаваемые для обработки PVM-потоков данных
Чтобы понять, как определенный пользователем класс можно использовать совместно с классом pvm_stream,попробуем усовершенствовать возможности PVM-палитры, представленной в главе 6. Класс палитры представляет простую коллекцию цветов. Для удобства будем сохранять цвета в векторе строк (vector)с именем Colors.
Начне м с объявления класса spectral_palette,который содержит friend-объявления дл я операторов вставки (<<) и извлечени я (>>).
// Листинг 11.16. Объявление класса spectral_palette
class spectral_palette : public pvm_object{
protected:
//. . .
vector Colors;
public:
spectral_palette(void);
//...
friend pvm_stream &operator>>(pvm_stream &In,spectral_palette &Obj);
friend pvm_stream &operator<<(pvm_stream &Out,spectral_palette &Obj);
//. . .
Обратите внимание на то, что класс spectral_paletteв листинге 11.16 наследует класс pvm_object.Класс pvm_objectтем самым обеспечивает своего наследника доступом к идентификатору задачи и идентификатору сообщения. Вспомните, что идентификаторы задачи и сообщения используются во многих PVM-функциях. С помощью определения операторов вставки (<<) и извлечения (>>) объекты класса spectral_paletteможно пересылать между параллельно выполняемыми PVM-задачами. Метод, используемый для класса spectral_palette,очень прост, и его можно так же успешно применить к любому пользовательскому классу. Поскольку класс pvm_streamдолжен иметь эти операторы для встроенных типов данных и контейнеров, которые содержат значения встроенных типов данных, в пользовательском классе необходимо определить только операторы "<<" и ">>" для перевода их представления в любой встроенный тип данных или стандартный контейнер. Вот как, например, определяется оператор "<<" для класса spectral_paletteв листинге 11.17.
// Листинг 11.17. Определение оператора для
// класса spectral_palette
pvm_stream &operator<<(pvm_stream &Out, spectral_palette &Obj)
{
int N;
string Source;
for(N = 0;N < Obj.Colors.size();N++) {
Source.append(Obj.Colors[N]);
if( N
Source.append(" ");
}
}
Out.reset();
Out.taskId(Obj.TaskId);
Out.messageId(Obj.MessageId);
Out << Source;
return(Out);
}
Рассмотрим подробнее определение этой операции вставки в листинге 11.17. Поскольку класс pvm_streamработает только со встроенными типами данных, цель пользовательского оператора "<<" — перевести пользовательский объект в последовательность значений встроенных типов данных. Этот перевод является одной из основных обязанностей классов, «отвечающих» за потоковое представление данных. В данном случае объект класса spectral_paletteдолжен быть переведен в строку «цветов», разделенных пробелами. Список цветовых значений сохраняется в строке Source.Рассматриваемый процесс перевода позволяет применить к объекту этого класса оператор "<<", который был определен для строкового типа данных. Имея определения этих операторов, API-интерфейс программиста становится более удобным, чем при использовании ори г инальных версий функций библиотеки Pthread, POSIX и MPI. Ведь теперь объект класса spectral_paletteможно переслать из одной PVM-задачи в другую, используя такую привычную операцию вставки (<<).
// Листинг 11.18. Использование объектов классов
// pvm_stream и spectral_palette
pvm_stream TaskStream;
spectral_palette MyColors;
//. . .
TaskStream.taskId(20001);
TaskStream.messageId(l); //.. .
TaskStream « MyColors; //.. .
Здесь объект MyColorsпересылается в соответствующую PVM-задачу. На рис. 11.6 показаны компоненты, используемые для поддержки объектов TaskStreamи MyColors.Каждый компонент на рис. 11.6 можно детализировать и оптимизировать в отдельности. Каждый представленный здесь уровень обеспечивает дополнительный слой изоляции от сложности этих компонентов. В идеале на самом высоком уровне программист должен заниматься только деталями, связанными с данной предметной областью. Такой высокий уровень абстракции позволяет программисту самым естественным образом представлять параллелизм, который вытекает из требований предметной области, не углубляясь при этом в синтаксис и сложные последовательности вызовов функций. Компоненты, представленные на рис. 11.6, следует рассматривать лишь как малую толику библиотеки классов, которую можно использовать для PVM-программ и многопоточных PVM-программ. Те же методы можно применять для взаимодействия между параллельно выполняемыми задачами, которые не являются частью PVM-среды. Ведь существует множество приложений, которые требуют реализации параллельности, но не нуждаются во всей полноте функционирования механизма PVM-cреды. Для таких приложений вполне достаточно использования функций ехес( ), fork() или pvm_spawn(). Примерами таких приложений могут служить программы, которые требуют создания нескольких параллельно выполняемых процессов, и приложения типа «клиент-сервер». Для таких нePVM -или неМРI-приложений также может потребоваться организация межпроцессного взаимодействия. Для параллельно выполняемых процессов, создаваемых посредством fork-exec-последовательности вызовов или функций pvm_spawn,имело бы смысл поддерживать потоковое представление данных. Понятие объектно-ориентированного потока данных можно также расширить с помощью каналов и FIFO-очередей.
Читать дальше