Параллельное и распределенное программирование на С++ - [58]

Шрифт
Интервал

Если значение параметра execute равно 0, указатель извлекается из вершины стека потока без выполнения routine -функции.

Необходимо позаботиться о том, чтобы для каждой функции занесения в стек (push) существовала функция извлечения из стека (pop) в пределах одной и той же лексической области видимости. Например, для функции funcA () обязательно выполнение cleanup -обработчика при ее нормальном завершении или аннулировании:

>void *funcA(void *X)

>{

> int *Tid;

> Tid = new int;

> // do some work

> //...

> pthread_cleanup_push(cleanup_funcA,Tid);

> // do some more work

> //...

> pthread_cleanup_pop(0);

>}

Здесь функция funcA( ) помещает указатель на обработчик cleanup_funcA( ) в стек завершающих процедур путем вызова функции pthread_cleanup_push (). Каждому обращению к этой функции должно соответствовать обращение к функции pthread_cleanup_pop(). Если функции извлечения указателя из стека (pop- функции) передается значение 0, то извлечение из стека состоится, но без выполнения обработчика. Обработчик будет выполнен лишь при аннулировании потока, выполняющего функцию funcA().

Для функции funcB () также требуется cleanup -обработчик:

>void *funcB(void *X)

>{

> int *Tid;

> Tid = new int;

> // do some work

> //...

> pthread_cleanup_push(cleanup_funcB,Tid);


> // do some more work

> //...

> pthread_cleanup_pop(1);

>}

Здесь функция funcB () помещает указатель на обработчик cleanup_funcB () в стек завершающих процедур. Отличие этого примера от предыдущего состоит в том, что функции pthread_cleanup_pop () передается параметр со значением 1, т.е. после извлечения из стека указателя на обработчик этот обработчик будет тут же выполнен. Необходимо отметить, что выполнение обработчика в данном случае состоится «при любой погоде», т.е. и при аннулировании потока, который обеспечивает выполнение функции funcB( ), и при обычном его завершении. Обработчики- «уборщики», cleanup_funcA() и cleanup_funcB (), — это обычные функции, которые можно использовать для закрытия файлов, освобождения ресурсов, разблокирования мьютексов и пр.

Управление стеком потока

Адресное пространство процесса делится на раздел кода, раздел статических данных, свободную память и раздел стеков. Стекам потоков выделяется область из стекового раздела процесса. Стек потока предназначен для хранения стекового фрейма, связанного с каждой процедурой (функцией), которая была вызвана, но еще не завершена. Стековый фрейм содержит временные переменные, локальные переменные, адреса точек возврата и любую другую дополнительную информацию, которая необходима потоку, чтобы найти «обратную дорогу» к ранее вызванным процедурам. При выходе из процедуры (функции) ее стековый фрейм извлекается из стека. Расположение фреймов в стеке схематично показано на рис. 4.12.

Предположим, что поток А (см. рис. 4.12) выполняет функцию task1 () , которая создает некоторые локальные переменные, выполняет заданную обработку, а затем вызывает функцию taskX (). При этом для функции task1 () создается стековый фрейм, который помещается в стек потока. Функция taskX () выполняет «свои» действия, создает локальные переменные, а затем вызывает функцию taskC (). Нетрудно догадаться, что стековый фрейм, созданный для функции taskX () , также помещается в стек. Функция taskC () вызывает функцию taskY() и т.д. Каждый стек должен иметь достаточно большой размер, чтобы поместить всю информацию, необходимую для выполнения всех функций потока, а также цепочки других подпрограмм, которые будут вызваны потоковыми функциями. Размером и местоположением стека потока управляет операционная система, но для установки и считывания этой информации предусмотрены методы, которые определены в объекте атрибутов потока.



Рис. 4.12. Стековые фреймы, сгенерированные потоками

Функция pthread_attr_getstacksize( ) возвращает минимальный размер стека, устанавливаемый по умолчанию. Параметр attr определяет объект атрибутов потока, из которого считывается стандартный размер стека. При успешном выполнении функция возвращает значение 0, а стандартный размер стека, выраженный в байтах, coxpaняется в параметре stacksize. В случае неудачи функция возвращает код ошибки.

Функция pthread_attr_setstacksize() устанавливает минимальный размер стека. Параметр attr определяет объект атрибутов потока, для которого устанавливается размер стека. Параметр stacksize содержит минимальный размер стека, выраженный в байтах. При успешном выполнении функция возвращает значение 0 , в противном случае - код ошибки. Функция завершается неудачно, если значение параметра stacksize оказывается меньше значения PTHREAD_MIN_STACK или превышает системный минимум. Вероятно, значение PTHREAD_STACK_MIN будет меньше минимального размера стека, возвращаемого функцией p thread_attr_getstacksize(). Прежде чем увеличивать минимальный размер стека потока, следует поинтересоваться значением, возвращаемым функцией p thread_attr_getstacksize() р азмер ст ека фиксируется, чтобы его расширение во время выполнения программы ограничивалось рамками фиксированного пространства стека, установленного во время компиляции.


Рекомендуем почитать
Pro Git

Разработчику часто требуется много сторонних инструментов, чтобы создавать и поддерживать проект. Система Git — один из таких инструментов и используется для контроля промежуточных версий вашего приложения, позволяя вам исправлять ошибки, откатывать к старой версии, разрабатывать проект в команде и сливать его потом. В книге вы узнаете об основах работы с Git: установка, ключевые команды, gitHub и многое другое.В книге рассматриваются следующие темы:основы Git;ветвление в Git;Git на сервере;распределённый Git;GitHub;инструменты Git;настройка Git;Git и другие системы контроля версий.



DirectX 8. Начинаем работу с DirectX Graphics

В книге рассказывается история главного героя, который сталкивается с различными проблемами и препятствиями на протяжении всего своего путешествия. По пути он встречает множество второстепенных персонажей, которые играют важные роли в истории. Благодаря опыту главного героя книга исследует такие темы, как любовь, потеря, надежда и стойкость. По мере того, как главный герой преодолевает свои трудности, он усваивает ценные уроки жизни и растет как личность.


Симуляция частичной специализации

В книге рассказывается история главного героя, который сталкивается с различными проблемами и препятствиями на протяжении всего своего путешествия. По пути он встречает множество второстепенных персонажей, которые играют важные роли в истории. Благодаря опыту главного героя книга исследует такие темы, как любовь, потеря, надежда и стойкость. По мере того, как главный герой преодолевает свои трудности, он усваивает ценные уроки жизни и растет как личность.


Обработка событий в С++

В книге рассказывается история главного героя, который сталкивается с различными проблемами и препятствиями на протяжении всего своего путешествия. По пути он встречает множество второстепенных персонажей, которые играют важные роли в истории. Благодаря опыту главного героя книга исследует такие темы, как любовь, потеря, надежда и стойкость. По мере того, как главный герой преодолевает свои трудности, он усваивает ценные уроки жизни и растет как личность.


Питон — модули, пакеты, классы, экземпляры

Python - объектно-ориентированный язык сверхвысокого уровня. Python, в отличии от Java, не требует исключительно объектной ориентированности, но классы в Python так просто изучить и так удобно использовать, что даже новые и неискушенные пользователи быстро переходят на ОО-подход.