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

>// Листинг 11.12. Объявление класса pvm_stream, который

>// наследует класс mios

>class pvm_stream : public mios{

>protected:

>int TaskId;

>int MessageId;

>mutex Mutex;

>//...

>public:

> void taskId(int Tid);

> void messageId(int Mid);

>pvm_stream(int Coding=PvmDataDefault);

>void reset(int Coding = PvmDataDefault);

>pvm_stream &operator<<(string &Data);

>pvm_stream &operator>>(string &Data);

>pvm_stream &operator>>(int &Data);

>pvm_stream &operator<<(int &Data);

>//. . .

>};

Этот класс обработки потоков данных предназначен для инкапсуляции состояния активного буфера в PVM-задаче. Операторы вставки "<<" и извлечения ">>" можно использовать для отправки и приема сообщений между PVM-процессами. Здесь мы рассмотрим использование этих операторов только для обработки строк и значений типа int. Интерфейс этого класса далек от совершенства. Поскольку этот класс предназначен для обработки данных любого типа, мы должны расширить определения операторов "<<" и ">>". А так как мы планируем использовать класс pvm_stream в многопоточной программе, мы должны быть уверены в том, что объект класса pvm_stream безопасен для потоков. Поэтому мы включаем в качестве члена нашего класса pvm_stream класс mutex. Поскольку сообщение может быть направлено для конкретной PVM-задачи, класс pvm_stream инкапсулирует для нее активный буфер. Наша цель — использовать классы ostream и istream в качестве «путеводителя» по функциям, которые должен иметь класс pvm_stream. Вспомним, что классы ostream и istream являются классами трансляции. Они переводят типы данных в обобщенные потоки байтов при выводе и обобщенные потоки байтов в конкретные типы данных при вводе. Используя классы istream и ostream, программисту не нужно погружаться в детали вставки в поток или выделения из потока данных того или иного типа. Мы хотим, чтобы и поведение класса pvm_stream было аналогичным. Библиотека PVM располагает различными функциями для каждого типа данных, которые необходимо упаковать в буфер отправки или распаковать из буфера приема. Например, функции pvm_pkdouble () pvm_pkint () pvm_pkfloat() используются для упаковки double-, int- и float-значений соответственно. Аналогичные функции существуют и для других типов данных, определенных в С++. Мы бы хотели поддерживать наше потоковое представление, т.е. чтобы ввод и вывод данных можно было представить как обобщенный поток байтов, который перемещается в программу или из нее. Следовательно, мы должны определить операторы вставки (<<) и извлечения (>>) для каждого типа данных, который мы собираемся использовать при обмене сообщениями между PVM-задачами. Мы также моделируем состояние потока данных в соответствии с классами istream и ostream, которые содержат компонент ios, предназначенный для хранения состояния этого потока. Поток данных может находиться в состоянии ошибки либо в одном из различных состояний, которые выражаются восьмеричным, десятичным или шестнадцатеричным числом. Поток также может пребывать в нормальном, заблокированном или состоянии конца файла. Класс pvm_stream должен не только содержать компонент, который поддерживает состояние потока данных, но и методы, которые устанавливают заданное или исходное состояние PVM-задачи, а также считывают его. Наш класс pvm_stream для этих целей содержит компонент mios. Этот компонент поддерживает состояние потока данных и активного буфера отправки и приема информации. На рис. 11.4 представлены две диаграммы классов: одна отображает отношения между основными классами библиотеки iostream, а вторая — отношения между классом pvm_stream и ero компонентами.