Как мне стать владельцем заброшенного boost::interprocess::interprocess_mutex?

StackOverflow https://stackoverflow.com/questions/1179685

Вопрос

Мой сценарий:один сервер и несколько клиентов (хотя и не так много).Сервер может отвечать только одному клиенту одновременно, поэтому они должны быть поставлены в очередь.Я использую мьютекс (boost::interprocess::interprocess_mutex) для этого заверните в boost::interprocess::scoped_lock.

Дело в том, что если один клиент неожиданно умирает (т.е.деструктор не запускается) при удержании мьютекса у других клиентов возникают проблемы, потому что они ожидают этого мьютекса.Я рассматривал возможность использования timed wait , поэтому, если мой клиент ожидает, скажем, 20 секунд и не получает мьютекс, он все равно переходит к серверу.

Проблемы, связанные с таким подходом:1) он делает это каждый раз.Если он находится в цикле, постоянно общаясь с сервером, ему нужно каждый раз ждать истечения тайм-аута.2) Если есть три клиента, и один из них умирает, удерживая мьютекс, два других просто подождут 20 секунд и одновременно свяжутся с сервером - именно то, чего я пытался избежать.

Итак, как я могу сказать клиенту: "эй, кажется, этот мьютекс был заброшен, возьмите его в свои руки"?

Это было полезно?

Решение

К сожалению, это не поддерживается boost::interprocess API как есть.Однако есть несколько способов, которыми вы могли бы это реализовать:

Если вы используете платформу POSIX с поддержкой pthread_mutexattr_setrobust_np, отредактируйте boost/interprocess/sync/posix/thread_helpers.hpp и boost /interprocess/sync/posix/interprocess_mutex.hpp, чтобы использовать надежные мьютексы и каким-то образом обработать возврат EOWNERDEAD из pthread_mutex_lock.

Если вы находитесь на какой-либо другой платформе, вы могли бы отредактировать boost /interprocess/sync/emulation/interprocess_mutex.hpp, чтобы использовать счетчик генерации с заблокированным флагом в младшем бите.Затем вы можете создать протокол восстановления, который установит флаг в слове блокировки, указывающий на ожидающее восстановление, затем по истечении времени ожидания выполните сравнение и замену, чтобы проверить, что в слове блокировки все еще присутствует то же поколение, и если это так, замените его заблокированным значением следующего поколения.

Если вы работаете в Windows, другим хорошим вариантом было бы использовать собственные объекты мьютекса;в любом случае, они, скорее всего, будут более эффективными, чем напряженное ожидание.

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top