mutex(void)
int lock(void);
int unlock(void);
int trylock(void);
int timedlock(void);
};
Объявив класс mutex, используем его для определения мьютексных пере
Функции-члены класса mutex определяются путем заключения в оболочку вызовов соответствующих Pthread-функций, например, так.
// Листинг 11.2. Функции-члены класса mutex
mutex::mutex(void) {
try{
int Value;
Value = pthread_mutexattr_int(Attr); //. . .
Value = pthread_mutex_init(Mutex,Attr); //. . .
}
int mutex::lock(void) {
int RetValue;
RetValue = pthread_mutex_lock(Mutex); //. . .
return(ReturnValue);
}
Благодаря инкапсуляции мы также защищаем переменные типа pthread_mutex_t * и pthread_mutexattr_t *. Другими словами, при вызове методов lock(), unlock(), trylock() и других нам не нужно беспокоиться о том, к каким мьютексным переменным или переменным атрибутов будут применены эти функции. Возможность скрывать информацию (посредством инкапсуляции) позволяет программисту писать вполне безопасный код. С помощью свободно распространяемых версий Рthread-функций этим функциям можно передать любую переменную типа pthread_mutex_t. Однако при передаче одной из этих функций неверно заданного мьютекса может возникнуть взаимоблокировка или отсрочка бесконечной длины. Инкапсуляция переменных типа pthread_mutex_t и pthread_mutexattr_t в к
Теперь мы можем использовать такой встроенный интерфейсный класс, как mutex, в любых других пользовательских классах, предназначенных для безопасной обработки потоков выполнения. Предположим, мы хотели бы создать очередь с многопоточной поддержкой и многопоточный класс pvm_stream. Очередь будем использовать для хранения поступающих событий для множества потоков, образованных в программе. На некоторые потоки возложена ответственность за отправку сообщений различным PVM-задачам. PVM-задачи и потоки выполняются параллельно. Несколько потоков выполнения разделяют единственный PVM-класс и единственную очередь событий. Отношения между потоками, PVM-задачами, очередью событий и классом pvm_stream показаны на рис. 11.1.
Очередь, показанная на рис. 11.1, представляет собой критический раздел, поскольку она совместно используется несколькими выполняемыми потоками. Класс pvm_stream — это также критический раздел и по той же причине. Если эти критические разделы не синхронизировать и не защитить, то данные в очереди и классе pvm_stream могут разрушиться. Тот факт, что несколько потоков могут одновременно обновлять либо очередь, либо код класса pvm_stream, открывает среду для «гонок». Чтобы не допустить этого, мы должны обеспечить нашу очередь и к
Обратите внимание на то, что класс x_queue содержит к
![]() |
![]() |
// Листинг 11.3. Объявление класса x_queue
template <class T> x_queue class{
protected:
queue<T> EventQ;
mutex Mutex;
//...
public:
bool enqueue(T Object);
T dequeue(void);
//...
};
Метод enqueue() используется для добавления элементов в очередь, а метод dequeue() — для удаления их из очереди. Каждый из этих методов рассчитан на использование oбъeктaMutex. Определение этих методов приведено в листинге 11.4.
// Листинг 11.4. Определение методов enqueue() и dequeue()
tempIate<class T> bool x_queue<T>::enqueue(T Object)
{