v << input.elements[i]; // Отсылка i-того значения массива
return v;
}
ostream& operator<<(ostream& v, const DVector& input)
{
v << input.length; // Запись значения length
for (int i=0; i<input.length; i++)
v << input.elements[i]; // Записьi-того значения массива
return v;
}
CCVoid& operator>>(CCVoid& v, DVector& output)
{
v >> output.length; // Прием значения length
output.elements = new double[output.length];
for (int i=0; i<output.length; i++)
v >> output.elements[i]; // Прием i-того значения массива
return v;
}
istream& operator>>(istream& v, DVector& output)
{
v >> output.length; // Чтение значения length
output.elements = new double[output.length];
for (int i=0; i<output.length; i++)
v >> output.elements[i]; // Чтение i-го значения массива
return v;
}
Рисунок 3.6: Использование функций передачи данных.
На рисунке 3.6 образец сообщения V, тип DVector которого определен пользователем, с помощью глобального указателя gp принимается на процессорном объекте pobj2 благодаря ссылке gp->transfer(V) в процессорном объекте pobj1 .
Функция << упаковывает структуру данных в источнике, а функция >> – распаковывает ее у получателя.
Тип CCVoid – определенный транслятором тип, аналогичный типам istream и ostream, использованному в iostream библиотеке. Для простых типов функции передачи данных генерируются транслятором CC++ автоматически. Для локальных указателей, массивов и структур, которые включают локальные указатели, функции передачи данных должны быть созданы программистом. Например, в тексте 3.7 показана передача данных и функции <iostream.h> для типа DVector, включающего двумерный вектор. Эти функции посылают длину вектора, сопровождаемую векторными компонентами, и получают эти значения в том же самом порядке. Ключевое словоfriend в спецификации C++ используют для имен функций не членов класса, которые, однако, могут обращаться к частным переменным класса. Определив эти функции передачи данных, можно (см. рис. 3.6) делать RPC с параметром DVector, который сформирован следующим образом:
DVector V;le[2];
V.length = 2;
V.elements[0] = 42.0;
V.elements[1] = 17.0;
gp->transfer(V);
Потребность в асинхронной связи может возникать тогда, когда вычислительные задачи должны обратиться к элементам структуры общих (разделяемых) данных неструктурированным способом (Раздел 2.3.4). Это требование может быть удовлетворено в CC++ тремя различными способами:
1) Структура разделяемых данных может быть включена в специализированный набор данных одновременно выполняемых задач, ориентированных на чтение или требование записи с использованием операций канала.
2) Структура разделяемых данных может быть распределена среди выполняемых задач. В этом случае каждая вычислительная задача в ожидании запросов на передачу должна периодически список сообщений опрашивать (poll – голосовать). Так, для поддержки операции опроса в тексте 3.6 достаточно расширить класс Queue, поместив в структуру IntQData добавочное поле, принимающее значения full или empty. Значение empty устанавливается, когда созданный элемент списка еще пуст, а full – когда значения данных помещены в список элементов. Функция опроса заключается в проверке состояния этого поля у элемента списка в голове очереди.
3) Третий вариант обращения к распределенным структурам разделяемых задачами данных непосредственно использует механизм RPC языка CC++. Прежде, чем сообщение будет послано в канал, задача обращается к данным другого процессорного объекта посредством RPC путем вызова соответствующей функции-члена. Простым примером записи с использованием удаленного вызова процедуры (RPC) является вызов функции get_x в тексте 3.1.
Уважаемый посетитель!
Чтобы распечатать файл, скачайте его (в формате Word).
Ссылка на скачивание - внизу страницы.