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

>class pvm_stream{

>protected:

>mutex Mutex;

>int TaskId;

>int MessageId;

>// . - -

>public:

>pvm_stream & operator <<(string X);

>pvm_stream & operator «(int X);

>pvm_stream &operator <<(float X);

>pvm_stream &operator>>(string X);

>//.. .

>};

Как и в классе x_queue, объект Mutex используется применительно к функциям, которые могут изменить состояние объекта класса pvm_stream. Например, мы могли определить один из операторов "«" следующим образом .

>// Листинг 11.6. Определение оператора << для

>// класса pvm_stream

>pvm_stream &pvm_stream::operator<<(string X) {

>//...

> pvm_pkbyte(const_cast(X.data()),X.size(),1);

> Mutex.lock();

> pvm_send(TaskId,MessageId);

> Mutex.unlock();

>//.. .

> return(*this);

>}

Класс pvm_stream использует объекты Mutex для синхронизации доступа к его критическому разделу точно так же, как это было сделано в классе x_queue. Важно отметить, что в обоих случалх инкапсулируются pthread_mutex-функции . Программист не должен беспокоиться о правильном синтаксисе их вызова. Здесь также используется более простой интерфейс для вызова функций lock () и unlock (). Более того, здесь нельзя перепутать, какую pthread_mutex_t*-nepeмeннyю нужно использовать с pthread_mutex-функциями. Наконец, программист может объявить несколько экземпляров класса mutex, не обращалсь снова и снова к функциям библиотеки Pthread. Раз мы сделали ссылку на Pthread-функции в определениях методов клlacca mutex, то теперь нам достаточно вызывать только эти методы.

Подробнее об объектно-ориентированном взаимном исключении и интерфейсных классах

Чтобы справиться со сложностью написания и поддержки программ с параллелизмом, попробуем упростить API-интерфейс с соответствующими библиотеками. В некоторых системах, возможно, имеет смысл создать библиотеки Pthreads, MPI, атакже стандартные функции использования семафоров и разделяемой памяти как часть единого решения. Все эти библиотеки и функции имеют собственные протоколы и синтаксис. Но у них есть много общего. Поэтому мы можем использовать интерфейсные классы, наследование и полиморфизм для создания упрощенного и непротиворечивого интерфейса, с которым непосредственно будет работать программист. Мы можем также скрыть от наших приложений детали реализации конкретной библиотеки. Если приложение опирается только на методы, используемые в наших интерфейсных классах, то оно будет защищено от изменений, вносимых в реализацию функций, обновлений библиотек и прочих «подводных» реструктуризации. В конце концов, работа над интерфейсом (интерфейсными классами) с компонентами параллелизма и библиотеками функций позволит существенно понизить уровень сложности параллельного программирования. Итак, рассмотрим подробнее, какие методы разработки интерфейсных классов можно реализовать для поддержки параллелизма.