Параллельное программирование: Учебное пособие, страница 58

3.4.1  Процессорные объекты

Процессорный объект определяется как обычный С++ класс объявлением переменной с модифицирующим ключевым словом global. Определение процессорного объекта идентично нормальному определению класса C++ за исключением двух моментов:

1.  В С++ имена переменных и функций, имеющих тип global, (имена в контексте файла) относятся к уникальным объектам лишь в пределах конкретного процессорного объекта. Поэтому исключено их совместное использование другими процессорными объектами.

2.  Частных членов процессорного объекта специально объявлять частными не требуется, так как в C++ функции и переменные типа global включают и частных членов того объекта, в котором они впервые были объявлены.

Типы процессорных объектов могут быть унаследованы и обычным механизмом C++, согласно которому частные функции и данные доступны только через функции, принадлежащие процессорным объектам. То есть интерфейс процессорного объекта определяется функциями-членами и данными, объявленными в определении класса как public.

Так, например, в тексте 3.3 создается класс процессорного объекта Construction с общими функциями-членами foundry и bridge. Класс ChannelUser здесь определен как базовый класс. Он обеспечивает доступ к канальным операциям, описанным в тексте 3.15, вызывая их посредством параметра Channel.

global class Construction: public ChannelUser

{

public:

void foundry(Channel, int);

voidbridge(Channel);

};

3.4.2  Глобальные указатели

Процессорный объект является локальным модулем, данные адресного пространства которого доступны с минимальными временными затратами. Процесс, выполняющийся в процессорном объекте, может обращаться прямо к структурам данных, определенных или распределенных в границах процессорного объекта, используя обыкновенные указатели языка C++.

Процессорные объекты связываются друг с другом при помощи глобальных указателей. Глобальный указатель подобен обыкновенному указателю C++ за исключением того, что он позволяет указать на другие процессорные объекты или структуры данных, находящиеся в границах других процессорных объектов. Они предоставляют данные, которые являются потенциально нелокальными и, следовательно, более затратными по времени обращения к данным.

Глобальный указатель отличается от переменной по ключевому слову global. Например:

float *global gpf;         // глобальный указатель на переменную

                                                      // gpf с плавающей точкой float

char **global gppc;      // глобальный указатель на указатель

                                                      // gppc символьного типа char

C *global gpC;                   // глобальный указатель на объект

                                                      // gpC типа C

Когда используется оператор new для создания отдельного процессорного объекта, то обращаются к указателю global. Например, в тексте 3.3 оператор

Construction *global foundry_pobj = new Construction;

создает новый процессорный объект типа Construction, который определяется указателем на объект foundry_pobj.

3.4.3  Размещение процесса

По умолчанию процесс в CC++ выполняется в том же самом процессорном объекте, где расположена и реализующая его программа. Программа вычислений, расположенная в другом процессорном объекте, выполняется через RPC. Процесс нуждается только в глобальном указателе на другой процессорный объект, чтобы использовать любую его общую функцию-члена. Например, в строке текста 3.3:

bridge_pobj->bridge();

bridge_pobj является глобальным указателем на процессорный объект, в котором программа будет выполняться, а bridge является общей функцией-членом того объекта. Большинство программ CC++ создают только один процесс в одном процессорном объекте.

В качестве второй задачи для демонстрации параллельных свойств СС++ возьмем алгоритм рекурсивного поиска решений на двоичном дереве [12, 13], в котором применяется динамическое создание задач для отдельных процессорных объектов и каналов связи:

procedure search(A)

begin