как эффективно ждать на семафорном наборе?

Я использую семафоры с разделяемой памятью для связи между несколькими производителями и несколькими клиентами. В моей системе есть два основных типа семафоров: «хранимые семафоры» и «обработанные семафоры».

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

Код производителя:

for(int i =0;i<nloop;i++){
usleep(100);
strcpy(shared_mem[i], "data for processing");
sem_post(&shared_mem[i].stored_semaphored);
if(sem_timedwait(&msg_ptr->processed_semaphore,&ts)==-1){ //waiting for result
if(errno == ETIMEDOUT){
}
break;
}else{
//success
}

}

код потребителя:

for (int j = 0; j < MAX_MESSAGE; j++) {
if (sem_trywait(&(shm_ptr->messages[j].stored_semaphore)) == -1) {
if (errno == EAGAIN) {
} else {
//success ==> process data
//post result back on the shared memory, and increase
//the processed semahore
strcpy(shared_mem[j].output, "Processed data");
sem_post(&(shared_mem[j].processed_semaphore));
}
}
}//for loop over MAX_MESSAGE

Моя проблема в том, что цикл for в коде потребителя тратит почти 100% ЦП, потому что в случае отсутствия данных от производителя, цикл for работает непрерывно.

Мой вопрос заключается в том, что есть какие-то другие способы ожидания на наборе семафоров (которые могут быть похожи на механизм ожидания с помощью SELECT, POLL или EPOLL), который не тратит время процессора.

Надеюсь увидеть ваш ответ. Спасибо!

0

Решение

Насколько я знаю, на семафорах ждать нельзя. Это означает, что все обращения должны проходить через один семафор. Вы перебираете множество семафоров, чтобы они вместе могли стать одним объектом. Этот потребитель должен знать, когда какой-либо из семафоров был сигнализирован, поэтому используйте дополнительный sem_post на новом семафоре, чтобы указать, что набор семафоров изменился.

Ваш код производителя становится примерно таким:

....
sem_post(&shared_mem[i].stored_semaphored);
sem_post(&list_changed_semaphore); /* Wake the consumer. */
....

и потребитель:

/* Block until a consumer has indicated that it has changed the semaphore list */
if (!sem_wait(&list_changed_semaphore)) {
/* At least one producer has signalled a change. */
for (int j = 0; j < MAX_MESSAGE; j++) {
if (sem_trywait(&(shm_ptr->messages[j].stored_semaphore)) == -1) {
}
}
}

Вместо того, чтобы использовать семафор для list_changed_semaphore Вы могли бы использовать pthread_cond_t переменная условия, чтобы указать, что что-то в вашем семафоре изменилось. list_changed_semaphore не должен быть счетчиком, как в примере, показанном здесь, он должен быть только одним битом, чтобы указывать, что производитель изменил список.

1

Другие решения

Других решений пока нет …