Код на С, есть массив, который иногда (редко) может динамически обновлятся
спецальным потоком. Другие потоки только читают из этого массива. Сейчас
все организовано простым mutex-ом, примерно так:
refresh.c:
...
pthread_mutex_lock(mutex);
refresh(my_array);
pthread_mutex_unlock(mutex);
...readers.c:
...
pthread_mutex_lock(mutex);
index = binary_search(val, my_array, my_array_size);
pthread_mutex_unlock(mutex);
...Но так не оптимально, каждый читатель блокирует других читателей, нужно
чтобы читатели друг друга не блокировали, а блокировали только писателя,
а писатель пускай блокирует всех. Как этого добиться? Спасибо!
Покурил маны :) Нашел то что нужно:pthread_rwlock_wrlock, pthread_rwlock_rdlock и их друзья..
Вопрос наверно закрыт, но если у вас есть предложение лучше чем это, тогда буду рад узнать и о нем :)
>Покурил маны :) Нашел то что нужно:
>
>pthread_rwlock_wrlock, pthread_rwlock_rdlock и их друзья..
>
>Вопрос наверно закрыт, но если у вас есть предложение лучше чем это,
>тогда буду рад узнать и о нем :)Почитайте еще о RCU (Read-Copy-Update)
>Почитайте еще о RCU (Read-Copy-Update)Спасибо, нашел библиотеку "Userspace RCU library" (liburcu)
http://lwn.net/Articles/262464/
http://www.lttng.org/files/urcu/Попробую разобраться в превосходствах на методом с pthread_
По-моему, если не писать под Альфу то всё будет ОК и без этой либы...
>Код на С, есть массив, который иногда (редко) может динамически обновлятся
>спецальным потоком. Другие потоки только читают из этого массива. Сейчас
>все организовано простым mutex-ом, примерно так:Можно сделать вообще без блокировок и дополнительных библиотек - пишущий поток создает копию массива, изменяет ее, потому атомарно обновляет указатель - читающие потоки будут работать уже с новым массивом.
Остается вопрос, когда удалить старый массив - нужно дождаться, чтобы его отпустили все читающие потоки, что можно сделать атомарным же счетчиком, который периодически проверять пишущим потоком и в случае обнуления удалять старый массив.
Кстати, напомните - даются ли в C какие-то гарантии по поводу атомарности операций икремента/декремента int и присвоения указателя? Если нет, то как их реализовать портабельно? Понятно, что можно обернуть в mutex'ы, но хочется менее криво и более эффективно на платформах где это возможно.
>
>Остается вопрос, когда удалить старый массив - нужно дождаться, чтобы его отпустили
>все читающие потоки, что можно сделать атомарным же счетчиком, который периодически
>проверять пишущим потоком и в случае обнуления удалять старый массив.
>покомментирую позже, когда буду дома
>Кстати, напомните - даются ли в C какие-то гарантии по поводу атомарности
>операций икремента/декремента int и присвоения указателя? Если нет, то как их
>реализовать портабельно? Понятно, что можно обернуть в mutex'ы, но хочется менее
>криво и более эффективно на платформах где это возможно.В gnu libc есть специальный atomic тип sig_atomic_t, есть ли он в C99, нужно проверить, вот:
http://www.gnu.org/s/libc/manual/html_node/Atomic-Types.html
>Кстати, напомните - даются ли в C какие-то гарантии по поводу атомарности
>операций икремента/декремента intНе даются
> и присвоения указателя?Это атомарно
> Если нет, то как их
>реализовать портабельно? Понятно, что можно обернуть в mutex'ы, но хочется менее
>криво и более эффективно на платформах где это возможно.В glib-е, например, есть атомарные операции
>[оверквотинг удален]
>readers.c:
>...
>pthread_mutex_lock(mutex);
>index = binary_search(val, my_array, my_array_size);
>pthread_mutex_unlock(mutex);
>...
>
>Но так не оптимально, каждый читатель блокирует других читателей, нужно
>чтобы читатели друг друга не блокировали, а блокировали только писателя,
>а писатель пускай блокирует всех. Как этого добиться? Спасибо!это называется семафор