MyStream >> Value;

Поскольку каждый из рассмотренных операторных методов возвращает ссылку на тип pvm_stream , операторы вставки и извлечения можно соединить в цепочку.

Mystream << Valuel << Value2;

Mystream >> Value3 >> Value4;

Используя этот простой синтаксис, программист изолирован от более громоздкого синтаксиса функций pvm_send, pvm_pk, pvm_upk и pvm_recv . При этом он работает с более знакомыми для него объектно-ориентированными потоками данных. В данном случае поток данных представляет буфер сообщений, а элементы, которые помещаются в него или извлекаются оттуда, представляют сообщения, которыми обмениваются между собой PVM-процессы. Вспомните, что каждый PVM-процесс имеет отдельное адресное пространство. Поэтому операторы '<<' и '>>' не только маскируют вызовы функций pvm_send и pvm_recv, они также маскируют заложенную в них организацию связи. Поскольку класс pvm_stream можно использовать в много-поточной среде, операторы вставки и извлечения данных должны обеспечивать безопасность потоков выполнения.

Класс pvm_stream (см. рис. 11.4) содержит класс mutex. Класс mutex можно использовать для защиты критических разделов, которые имеются в классе pvm_stream. Класс pvm_stream инкапсулирует доступ к буферу отправки и буферу приема данных. Взаимодействие потоков выполнения и класса pvm_stream с буферами pvm_send и pvm_receive показано на рис. 11.5.

Рис.11.5. Взаимодействие потоков выполнения и класса pvm_stream с буферами pvm_send и pvm_receive

Критическими разделами являются не только буферы отправки и приема данных. Класс mios, используемый для хранения состояния класса pvm_stream, также является критическим разделом. Для защиты этого компонента можно использовать класс mutex.

При обращении к операторам вставки и извлечения данных можно использовать объект Mutex.

// Листинг 11.15.

//Определение операторов «<<» и «>>» для класса pvm_stream

pvm_stream &pvm_stream::operator<<(int Data) {

//.. .

Mutex.lock(); reset();

pvm_pkint(&Data,1,1); pvm_send(TaskId,MessageId); Mutex.unlock(); //.. .

return(*this);

}

pvm_stream &pvm_stream::operator>>(int &Data) {

int BufId; //. . .

Mutex.lock();

BufId = pvm_recv(TaskId,MessageId);

StreamState = pvm_upkint(&Data,1,1);

Mutex.unlock();

//. . .

return(*this);

}

Этот вид защиты позволяет сделать класс pvm_stream безопасным. Здесь мы не представили код обработки исключений или другой код, который бы позволил предотвратить бесконечные отсрочки или взаимную блокировку. Основнал идея в данном случае — сделать акцент на компонентах и вариантах архитектуры, которые пригодны для поддержки параллелизма. Интерфейсный класс mutex и класс pvm_stream можно использовать многократно, и оба они поддерживают параллельное программирование. Предполагается, что объекты класса pvm_stream должны использоваться PVM-задачами при отправке и приеме сообщений. Но это не является жестким требованием. Для того чтобы пользователь мог применить концепцию класса pvm_stream к своим классам, для них необходимо определить операторы вставки (<<) и извлечения (>>).

Пользовательские классы, создаваемые для обработки PVM-потоков данных

Чтобы понять, как определенный пользователем класс можно использовать совместно с классом pvm_stream, попробуем усовершенствовать возможности PVM-палитры, представленной в главе 6. Класс палитры представляет простую коллекцию цветов. Для удобства будем сохранять цвета в векторе строк (vector<string>) с именем Colors.

Начне м с объявления класса spectral_palette, который содержит friend- объявления дл я операторов вставки (<<) и извлечени я (>>).

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

class spectral_palette : public pvm_object{

protected:

//. . .

vector<string> 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)

Добавить отзыв
ВСЕ ОТЗЫВЫ О КНИГЕ В ИЗБРАННОЕ

0

Вы можете отметить интересные вам фрагменты текста, которые будут доступны по уникальной ссылке в адресной строке браузера.

Отметить Добавить цитату