асса
x_queue как шаблонного.
Рис.11.1. Отношения между потоками, PVM-задачами, очередью событий и классом pvm_stream в PVM-программе |
Рис.11.2. Диаграмма классов для пользовательских классов x_queue и pvm_stream |
// Листинг 11.3. Объявление класса x_queue
>template x_queue class{
>protected:
>queue EventQ;
>mutex Mutex;
>//...
>public:
>bool enqueue(T Object);
>T dequeue(void);
>//...
>};
Метод enqueue() используется для добавления элементов в очередь, а метод dequeue() — для удаления их из очереди. Каждый из этих методов рассчитан на использование oбъeктaMutex. Определение этих методов приведено в листинге 11.4.
>// Листинг 11.4. Определение методов enqueue() и dequeue()
>tempIate bool x_queue::enqueue(T Object)
>{
>Mutex.lock(); EventQ.push(Object); Mutex.unlock();
>}
>Leinplr.te T x_queue::dequeue(void)
>{
>T Object; //. . .
>Mutex.lock();
>Object = EventQ.front()
>EventQ.pop();
>Mutex.unlock() ;
>//. . .
>return(Object);
>}
Теперь очередь может функционировать (принимать новые элементы и избавляться от ненужных) в многопоточной среде. ПотокВ (см. рис.11.1) добавляет элементы в очередь, а потокА удаляет их оттуда. Класс mutex является интерфейсным классом. Он заключает в оболочку функции pthread_mutex_lock (), pthread_mutex_unlock (), pthread_mutex_init() и pthread_mutex_trylock(). Класс x_queue также является интерфейсным, поскольку он адаптирует интерфейс для встроенного класса queue . Прежде всего, он заменяет интерфейсы методов push() и pop() методами enqueue() и dequeue() . При этом операции вставки и удаления элементов из очереди заключаются между вызовами методов Mutex.lock() и Mutex.unlock(). Поэтому в первом случае мы используем интерфейсный класс для инкапсуляции переменных типа pthread_mutex_t* и pthread_mutexattr_t*, а также заключаем в интерфейсную оболочку несколько функций из библиотеки Pthread. А во втором случае мы используем интерфейсный класс для адаптации интерфейса класса queue. Еще одно достоинство класса mutex состоит в том, что его легко использовать в других классах, которые содержат критические разделы или области.
Класс pvm_stream (см. рис. 11 1) также является критическим разделом, поскольку оба потока выполнения (А и В) имеют доступ к потоку данных. Опасность возникновения «гонок» данных здесь вполне реальна, поскольку потокА и поток В могут получить доступ к потоку данных одновременно. Следовательно, мы используем класс mutex в нашем классе pvm_stream для обеспечения необходимой синхронизации.
>// Листинг 11.5. Объявление класса pvm_stream