У меня есть несколько упреждающих (асинхронных) потоков (TA), которым требуется временный доступ к общему ресурсу. Это типичное использование для pthread_mutex
.
Однако у меня есть несколько вещей, которые усложняют это:
У меня мало контроля над полным кодом, потому что я предоставляю только набор функций для упрощения процедуры.
Существует набор «основных» потоков (TM), над которыми я мало контролирую и которые используют частный мьютекс для доступа к указанному общему ресурсу. Они используют частный планировщик, который управляет этими потоками, таким образом, что в любой момент разрешено запускать только один, эффективно действуя совместно этими потоками.
Любой из этих основных потоков (TM) может вызвать запуск асинхронных потоков (TA). Это все часть кода программиста, которому я хочу предоставить дополнительные функции.
Мне нужно подождать, пока эти потоки ТМ не перейдут в «безопасное» состояние, когда я смогу разрешить потокам ТА получить доступ к общему ресурсу. У меня есть способ сделать это.
Таким образом, идея состоит в том, чтобы приостановить (заблокировать) все потоки TA до тех пор, пока это безопасное состояние не будет достигнуто в любом из потоков TM, затем приостановить этот поток TM, позволить каждому из потоков TA запускаться один за другим, и возобновить ветку ТМ, как только все будет готово.
Когда потоки ТМ достигнут указанного безопасного состояния, будет вызвана моя функция shared_resource_is_safe()
.
Кроме того, программист должен будет вызывать мои функции acquire_access()
и surrender_access()
до и после доступа к общему ресурсу.
Итак, мне нужно реализовать три функции, и я борюсь с использованием мьютексов и / или семафоров для достижения своей цели.
Вот что я придумал:
dispatch_semaphore_t semaphore;
pthread_mutex_t mutex;
int is_safe = 0;
void setup_once() {
semaphore = dispatch_semaphore_create (0);
pthread_mutex_init (&mutex, NULL);
}
void acquire_access() {
pthread_mutex_lock (&mutex);
dispatch_semaphore_wait (semaphore, DISPATCH_TIME_FOREVER);
assert(is_safe);
}
void surrender_access() {
pthread_mutex_unlock (&mutex);
}
void shared_resource_is_safe() {
// this shall resume thread that's called acquire_access()
is_safe = 1;
while (dispatch_semaphore_signal (semaphore) != 0) {
// Wait until the signaled thread
// has called surrender_access()
pthread_mutex_lock (&mutex);
pthread_mutex_unlock (&mutex);
}
is_safe = 0;
}
Семафор используется для любого потока, вызывающего acquire_access()
для ожидания shared_resource_is_safe()
.
Мьютекс должен убедиться, что все асинхронные потоки ожидают shared_resource_is_safe()
, позволяя ему работать.
Это не работает надежно, хотя. Я сталкиваюсь со случаями, когда утверждение для is_safe
не выполняется в асинхронных потоках, то есть основной поток не ожидает асинхронных потоков для вызова surrender_access()
. Что я делаю не так?