C ++, что и / или где выполняет pthread? - PullRequest
1 голос
/ 17 февраля 2012

Я построил многопоточный производитель-потребитель (добавить в очередь, потреблять из очереди, используя многочисленные потоки), но я пытаюсь оптимизировать это дальше, отправляя новый product () непосредственно в потоки выполнения, если они простаивают (вместо того, чтобы ставить их в очередь).

Итак, мне нужно выяснить, где в данный момент выполняется поток (в настоящее время он находится в состоянии условного ожидания или выполняет что-то). Кто-нибудь может предложить способ сделать это?

Ответы [ 4 ]

1 голос
/ 17 февраля 2012

Это то, что очередь уже должна делать.

Во-первых, поток не может быть бездействующим, если очередь не пуста, верно?

Так, что делает ваша операция "постановка в очередь и сигнал"делать?Он помещает указатель на данные, где поток может их найти, а затем указывает потоку работать с данными.Это минимальная задача, чтобы делать то, что вы хотите делать в любом случае.

Так что оптимизация невозможна.

1 голос
/ 17 февраля 2012

Если поток выполнения простаивает, не будет ли он ждать в очереди?Самый быстрый способ заставить его работать, это, вероятно, просто отправить его в очередь.

У вас есть основания полагать, что очередь является узким местом?

0 голосов
/ 17 февраля 2012

Вы можете сделать это, но если вы действительно хотите, это другое дело - см. Другие сообщения.

Во-первых, забудьте обо всех пользовательских потоках, ожидающих общего семафора. Чтобы сделать то, что вы хотите, ожидающие потоки потребителя должны быть адресованы экземпляром. Чтобы сделать это, потребитель, который появляется, блокирует очередь и находит ее пустой, должен ждать своего собственного события. Кроме того, потребитель должен предоставить в своем вызове pop адрес того места, куда он хочет поместить объект. Таким образом, в дополнение к «нормальной» очереди объектов, потребительским потокам, которые должны ждать, нужна структура, содержащая указатель и событие для ожидания. Вы можете создать массив или циклический буфер из этих wait_structs при создании очереди P-C.

Тогда все готово.

ПРОИЗВОДИТЕЛЬ: (вызывает push с объектом ref / ptr) Получает блокировку очереди и проверяет список wait_structs. Если есть запись, она загружает свой объект в адрес, на который указывает указатель wait_struct (то есть «отправка нового продукта () непосредственно в поток выполнения»), и сигнализирует о событии wait_struct. Если в списке wait_structs нет записи, производитель помещает свой объект в очередь объектов. Ах да - снимает блокировку очереди:)

ПОТРЕБИТЕЛЬ: (вызывает всплывающее окно с адресом, на который он хочет вернуть объект) Получает блокировку очереди и проверяет счетчик очереди объектов. Если он не равен нулю, он выталкивает объект, помещает его в целевой адрес, который он предоставил, снимает блокировку и запускается. Если очередь объектов пуста, потребитель получает бесплатный wait_strut в списке wait_structs, устанавливает указатель на значение, которое он передал, снимает блокировку очереди и ожидает события. Когда событие получает сигнал, у потребителя уже есть свой объект (запущенный производителем), и он может просто продолжаться - не нужно снова посещать очередь ПК.

Да, этот дизайн работает (в любом случае в Delphi - должен работать в C ++) и быстрее, чем «классическая» основанная на семафорах ПК-очередь (которая быстрее, чем Windows Message Queue, которая быстрее очередь IOCP).

У меня это работает с таймаутом - я дам вам понять, как это сделать. (Подсказка - вы должны использовать местоположение объекта-потребителя (адресуемое переданным указателем) в качестве временного хранилища:)

0 голосов
/ 17 февраля 2012

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

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

...