Re: Deadlock-prevention алгоритм
От: sokel Россия  
Дата: 30.06.14 11:17
Оценка:
Здравствуйте, Lazin, Вы писали:

L>read блокировку можно проапгрейдить до write блокировки при желании. Моя реализация R/W Lock сильно смещена в сторону читателей и предназначена для случаев, когда запись происходить на несколько порядков реже чем чтение (например для защиты настроек программы). В этом случае read_lock работает в 2-3 раза быстрее чем pthread_rwlock_rdlock. Также возможно, что pthread_rwlock_rdlock лучше масштабируется с ростом количества ядер/процессоров, чем моя реализация.


Тут всё зависит от того, как фишка ляжет. Предположим два потока постоянно читают один и тот же объект из настроек, т.е. составляющая хэша для конкретно этого объекта будет постоянной. И если трёхбитный хэш от thread_id у них различается — повезло, а вот если совпадёт, получаем mutual exclusion при доступе. pthread_rwlock в этом плане стабильней.

Можно сделать rwlock на mutex + conditional_variable. Только опасно, нужно помнить про read/write starvation.

как то так

Обобщил lock_pool для mutex/rwlock (без biased hash). lock_type как и размер пула параметрами шаблона. Заменил указатели на ссылки. Блокировка lock_type на чтение через внешнюю ф-цию, lock_for_reading.
hash функция тоже внешняя, size_t lock_hash(T const&, size_t lock_count) c default реализацией по адресу объекта. Иногда полезно например hash брать по ID какому то...
Плюс для guard'ов общую базу добавил (auto для бедных, как когда то его Кодт назвал).

#include "syncope.hpp"

typedef syncope::lock_pool<syncope::write_starvation_lock, 256> test_pool;
test_pool foo_sync("foo sync");

struct foo { foo(int id) : id(id) {} int id; };
inline size_t lock_hash(const foo& obj, size_t lock_count) {
    return obj.id%lock_count;
}

int main()
{
    foo a(1), b(2), c(3);
    {
        syncope::pool_guard guard1 = foo_sync.synchronize_read(a, b);
        std::cout << "read locked 1" << std::endl;
        syncope::pool_guard guard2 = foo_sync.synchronize_read(a, b);
        std::cout << "read locked 2" << std::endl;
    }
    {
        syncope::pool_guard guard = foo_sync.synchronize(a, b, c);
        std::cout << "write locked" << std::endl;
    }
    return 0;
}


выводит
foo sync read lock 1
foo sync read lock 2
read locked 1
foo sync read lock 1
foo sync read lock 2
read locked 2
foo sync unlock 2
foo sync unlock 1
foo sync unlock 2
foo sync unlock 1
foo sync lock 1
foo sync lock 2
foo sync lock 3
write locked
foo sync unlock 3
foo sync unlock 2
foo sync unlock 1
Re[25]: Deadlock-prevention алгоритм
От: Evgeny.Panasyuk Россия  
Дата: 30.06.14 11:28
Оценка: 31 (2) +1
Здравствуйте, B0FEE664, Вы писали:

L>>Дедлок — по определению непредусмотренное поведение программы.

BFE>Не более, чем исключение.

Всё же deadlock (незапланированный) это ошибка в коде программы — то есть не исключение, а скорее assert.
Можно конечно представить некий fault tolerance, который закладывается и на такие баги кода, но имхо кидать исключение в таком случае всё равно не лучший вариант.
Re: Deadlock-prevention алгоритм
От: MasterZiv СССР  
Дата: 30.06.14 11:50
Оценка:
> Теперь собственно вопрос — хочется специальный дефайн, при определении
> которого, включались бы проверки корректности порядка захвата и
> освобождения блокировок.

#define не нужен, поскольку эти проверки должны проходить в рантайме
всегда, поскольку порядок функционирования участков кода не
предопределён заранее. Если у вас не так, и вы решили проблему абсолютно
полного тестового покрытия всех ветвей вашей программы, только тогда --
да, нужен #define для сборки в особом режиме.

Про графы: если делать по уму, то по идее граф должен выродиться
в линейный список мьютексов. Т.е. я хочу сказать, что то, что вы
делаете, обычно делают (видимо) проще -- лочат мьютексы в строго
определённом порядке.
Posted via RSDN NNTP Server 2.1 beta
Re[26]: Deadlock-prevention алгоритм
От: B0FEE664  
Дата: 30.06.14 12:40
Оценка:
Здравствуйте, landerhigh, Вы писали:

BFE>>>>Обнаружили дедлок — бросили исключение. А как обработать исключение — понятно. В чём проблема-то?

L>Исключение — это исключительная ситуация, которая, однако, ожидаема и может быть исправлена.
Если вы ожидаете deadlock, то deadlock — это исключительная ситуация, которая, однако, ожидаема и может быть исправлена.
Придумайте что-нибудь посерьёзнее в качестве аргумента.

L>Некоторые ковбои пытаются ловить и "обрабатывать" и неисправимые ситуации — вроде конца света памяти или 0x5 (под виндой), но это неправильно, т.к. исправить ситуацию уже нельзя.

L>Дедлок по определению ситуация не ожидаемая. Если она ожидается, то ее всегда можно исправить в коде и полностью исключить.
Тогда давайте писать без исключений, раз исключение — ожидаемое событие, то ее всегда можно исправить в коде и полностью исключить.

L>>>Дедлок — по определению непредусмотренное поведение программы.

BFE>>Не более, чем исключение.
L>О майн готт. Не знаю, смеяться или плакать.
Я вижу одни эмоции без аргументов. Если вы можете обнаружить deadlock в момент исполнения, то он является одной из исключительных ситуаций. Разумеется для этого надо иметь механизм обнаружения deadlock в момент захвата очередного мютекса.

L>>>Ну бросил ты исключение? Что ты с ним делать будешь, ты ж не предполагал, что дедлок может возникнуть?

BFE>>Зато я предпологал, что может быть исключение.
L>>>Или ты уже предполагаешь, что дедлоки могут возникнуть и уже написал класс DeadLockException?
BFE>>Как вариант.
L>И что ты будешь с ним делать?
здесь
Автор: B0FEE664
Дата: 27.06.14


L>>>Тогда лучше потратить это время с бОльшей пользой и таки исправить поведение программы, чтобы исключить саму возможность дедлока.

BFE>>А где обоснование этого утверждения? Предполагать исключение придётся в любом случае, а значит обработка исключений должна быть в любом случае.
L>Дедлок возникает в результате не предусмотренной (не замеченной, проигнорированной) во время разработки взаимоблокировки двух или более потоков. Поскольку эта ситуация в принципе не предусматривалась, точнее, была прохлопана ушами, корректно обработать ее в рантаймне не-воз-мож-но.
Да уж, "обоснованице". Ну а как вам такое "контробоснование":
std::invalid_argument исключение возникает в результате не предусмотренной (не замеченной, проигнорированной) во время разработки передачи невалидного параметра в какую-то функцию. Поскольку эта ситуация в принципе не предусматривалась, точнее, была прохлопана ушами, корректно обработать ее в рантаймне не-воз-мож-но.
— это что? Это обоснование?

L>>>Тогда нужно проектировать правильно, без вариантов. В общем случае ты отктаться не сможешь.

BFE>>В общем случае много чего невозможно.
L>Проектировать правильно — возможно.
Что и предлагается сделать с помощью библиотеки.
И каждый день — без права на ошибку...
Re[26]: Deadlock-prevention алгоритм
От: B0FEE664  
Дата: 30.06.14 12:51
Оценка: -1
Здравствуйте, Evgeny.Panasyuk, Вы писали:

L>>>Дедлок — по определению непредусмотренное поведение программы.

BFE>>Не более, чем исключение.
EP>Всё же deadlock (незапланированный) это ошибка в коде программы — то есть не исключение, а скорее assert.
Нет, это не ошибка, если такое поведение ускоряет выполнение приложения и было предусмотрено заранее.

EP>Можно конечно представить некий fault tolerance, который закладывается и на такие баги кода, но имхо кидать исключение в таком случае всё равно не лучший вариант.

Всяко лучше, чем убивать подвисшие нитки извне, как это делают некоторые.
И каждый день — без права на ошибку...
Re[2]: Deadlock-prevention алгоритм
От: sokel Россия  
Дата: 30.06.14 12:58
Оценка:
Здравствуйте, sokel, Вы писали:

S>Плюс для guard'ов общую базу добавил (auto для бедных, как когда то его Кодт назвал).


Ну и совсем версия для бедных, без C++11.
Re[26]: Deadlock-prevention алгоритм
От: Lazin Россия http://evgeny-lazin.blogspot.com
Дата: 30.06.14 13:07
Оценка:
EP>Всё же deadlock (незапланированный) это ошибка в коде программы — то есть не исключение, а скорее assert.
EP>Можно конечно представить некий fault tolerance, который закладывается и на такие баги кода, но имхо кидать исключение в таком случае всё равно не лучший вариант.

В некоторых случаях, иметь такой механизм в продакшене может быть полезно, если например сервис работает под управлением супервизора, который перезапускает его в случае падения. Если сервис просто зависнет из-за дедлока, супервизор будет думать что все хорошо (если между супервизором и сервисом нет какого-нибудь протокола для проверки работоспособности) и не растартанет сервис. В этом случае лучше обнаружить дедлок и вызвать terminate.
Re[2]: Deadlock-prevention алгоритм
От: Lazin Россия http://evgeny-lazin.blogspot.com
Дата: 30.06.14 13:10
Оценка:
Я позже посмотрю, сейчас работу нужно работать
У тебя нет гитхаб аккаунта? Можно было бы сделать форк+pull request, что бы ты появился в списке контрибьюторов.
Re[27]: Deadlock-prevention алгоритм
От: landerhigh Пират  
Дата: 30.06.14 13:11
Оценка:
Здравствуйте, B0FEE664, Вы писали:

L>>Исключение — это исключительная ситуация, которая, однако, ожидаема и может быть исправлена.

BFE>Если вы ожидаете deadlock, то deadlock — это исключительная ситуация, которая, однако, ожидаема и может быть исправлена.

Скажу резко — если вы в своем коде ожидаете дедлок, то вам лучше не заниматься многопоточным программированием. По крайней мере пока.

BFE>Придумайте что-нибудь посерьёзнее в качестве аргумента.


Серьезнее некуда.

L>>Некоторые ковбои пытаются ловить и "обрабатывать" и неисправимые ситуации — вроде конца света памяти или 0x5 (под виндой), но это неправильно, т.к. исправить ситуацию уже нельзя.

L>>Дедлок по определению ситуация не ожидаемая. Если она ожидается, то ее всегда можно исправить в коде и полностью исключить.
BFE>Тогда давайте писать без исключений, раз исключение — ожидаемое событие, то ее всегда можно исправить в коде и полностью исключить.

Ради бога, занимайтесь километрами спагетти-кода с кодами возврата.
Исключения — не более чем механизм для корректного сообщения о проблеме, делающей невозможным продолжение работы на данном уровне вложенности, на предыдущие уровни для того, чтобы они могли принять соответствующее решение. Для этого они подходят как нельзя лучше. Но вот для лечения дефектов внутиутробного развития ПО они не подходят.

L>>>>Дедлок — по определению непредусмотренное поведение программы.

BFE>>>Не более, чем исключение.
L>>О майн готт. Не знаю, смеяться или плакать.
BFE>Я вижу одни эмоции без аргументов. Если вы можете обнаружить deadlock в момент исполнения, то он является одной из исключительных ситуаций.

Видимо, придется плакать.
Обнаруживать дедлок в момент исполнения уже поздно. Как в моем примере с однопутной железной дорогой.

L>>>>Ну бросил ты исключение? Что ты с ним делать будешь, ты ж не предполагал, что дедлок может возникнуть?

BFE>>>Зато я предпологал, что может быть исключение.
L>>>>Или ты уже предполагаешь, что дедлоки могут возникнуть и уже написал класс DeadLockException?
BFE>>>Как вариант.
L>>И что ты будешь с ним делать?
BFE>здесь
Автор: B0FEE664
Дата: 27.06.14


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


А если предыдущее состояние тех данных невосстановимо? А если это не данные, а команда на открытие воздушного прервыателя на 300 КВ, у которого trip time под десять секунд и наработка на отказ всего несколько десятков переключений и при попытке получить его текущий статус твой тред залип? Ты хочешь послать команду на закрытие, чтобы "восстановиться и попробовать снова"? Боюсь, тебе даже не дадут забрать свои вещи из кьюбилка, если ты такое предложишь, потому что этот факап может стоить кому-то жизней, а компании — многомиллионных судебных исков.

Дедлок в общем случае — не восстанавливаемая ситуация. Period.
Факт дедлока говорит о серьезном факапе в execution flow и рассчитывать на то, что тебе удастся откатиться, нельзя.

BFE>>>В общем случае много чего невозможно.

L>>Проектировать правильно — возможно.
BFE>Что и предлагается сделать с помощью библиотеки.

Еще раз — исправлять косяки проектирования в рантайме поздно. И в общем случае невозможно.
www.blinnov.com
Re[20]: Deadlock-prevention алгоритм
От: Lazin Россия http://evgeny-lazin.blogspot.com
Дата: 30.06.14 13:28
Оценка:
L>Зачем ты ее поломал?

Я ничего не делал, она сама просто взяла и загорелась

L>>Ну так остальные запросы простаивать то тоже не будут, они будут обслуживаться другими ядрами, так как запрос может обработать любое ядро.


L>А остальных запросов-то и нет. Всем нужен кот.


Это вырожденный случай, но даже в этом случае можно сделать так, чтобы к коту могли обращаться из разных потоков параллельно, если реплицировать самого кота и периодически reduce-ить его состояние (то что наимзеняли из разных потоков сливать вместе). Но это уже будет eventualy consistent реализация.

L>>Я говорю о моем репозитории с кодом из первого поста. Если все это тлен, как ты говоришь, то зря я парюсь, нужно удалить его и все. Eine Frau, ein Loch, eine mutex!


L>Речь не об одном мьютексе, а об архитектуре. И таки да, я буду продолжать утрвеждать, что детекторы дедлоков имеют мало смысла с точки зрения верификации ПО. Если архитектура настолько ущербна, что допускает дедлоки, то ничего, кроме ее переработки, не поможет. Детектор может помочь выявить и даже несколько дедлоков, но он не способен гарантировать отсутствие других, не обнаруженных пока, локов. Как инструмент раскопок в говнокоде, который нужно заставить хоть как-то работать, их использовать можно. Вопрос только, нужно ли?


Ты меня тогда не понял, видимо. Я в курсе что нужно делать хорошую архитектуру, в которой невозможны дедлоки и не делать плохую. Дело в том, что я прячу отдельные мьютексы за интерфейсом и говорю что объекты можно лочить так и так. Пользователь может решить (ошибочно), что он лочит разные объекты и дедлок невозможен в принципе, даже если он это делает в разном порядке, так как объекты реально разные и его архитектура это гарантирует, это и было бы так, если бы он использовал мьютексы напрямую, но у меня может получиться конфликт и возникнет дедлок. Поинт в том, что если ты берешь на себя захват/освобождение мьютексов а также сам мапишь их на разные объекты программы — ты также должен предоставить механизм проверки корректности. Period. Нормальная библиотека должна учитывать разные аспекты ее использования, не только основную логику и производительность, но и тестируемость, отлаживаемость и человеко-понимаемость.

L>Они как минимум убирают необходимость в 100500 явных блокировок.

atomic-и это тоже синхронизация

L>>Есть задачи где на один сервер может валиться больше. Статистика гугла показывает запросы пользователей. Получается, что на предыдущей работе у нас сервер, занимающийся сбором time-series данных от сенсоров обрабатывал больше запросов на запись в секунду, чем весь гугл? А может ты просто теплое с мягким сравниваешь? Я могу сказать с уверенностью, что всякие time-series данные от всяких сенсоров,


L>Ты кагбы можешь мне это не рассказывать, для меня IEC61850, MODBUS, BACNET, DNP3 и прочие страшные слова — вовсе не пустой звук. Но мы подобных проблем почему-то не имеем.

софт о котором я говорил не имеет подобных проблем, просто приведен в качестве примера сервиса, обрабатывающего столько данных, сколько по твоему не бывает он используется, например, в ЦДУ СО ЕЭС (судя по использованным аббревиатурам ты должен знать что это такое) для сбора всей телеметрии, какая только есть
Re[27]: Deadlock-prevention алгоритм
От: Evgeny.Panasyuk Россия  
Дата: 30.06.14 13:37
Оценка:
Здравствуйте, Lazin, Вы писали:

EP>>Всё же deadlock (незапланированный) это ошибка в коде программы — то есть не исключение, а скорее assert.

EP>>Можно конечно представить некий fault tolerance, который закладывается и на такие баги кода, но имхо кидать исключение в таком случае всё равно не лучший вариант.
L>В некоторых случаях, иметь такой механизм в продакшене может быть полезно, если например сервис работает под управлением супервизора, который перезапускает его в случае падения. Если сервис просто зависнет из-за дедлока, супервизор будет думать что все хорошо (если между супервизором и сервисом нет какого-нибудь протокола для проверки работоспособности) и не растартанет сервис.

То что такой механизм (для fault tolerance) в некоторых случаях (скорее редких) полезен, и даже необходим — я полностью согласен.
Но вот использовать исключения для сигнализации deadlock'а — имхо не лучший вариант.

L>В этом случае лучше обнаружить дедлок и вызвать terminate.


Так о том и речь, что например terminate был бы лучше исключения.
Re[28]: Deadlock-prevention алгоритм
От: B0FEE664  
Дата: 30.06.14 13:58
Оценка:
Здравствуйте, landerhigh, Вы писали:

L>>>Исключение — это исключительная ситуация, которая, однако, ожидаема и может быть исправлена.

BFE>>Если вы ожидаете deadlock, то deadlock — это исключительная ситуация, которая, однако, ожидаема и может быть исправлена.
L>Скажу резко — если вы в своем коде ожидаете дедлок, то вам лучше не заниматься многопоточным программированием. По крайней мере пока.
BFE>>Придумайте что-нибудь посерьёзнее в качестве аргумента.
L>Серьезнее некуда.
Вы в самом деле считаете переход на личность серьёзным аргументом?

L>>>>>Дедлок — по определению непредусмотренное поведение программы.

BFE>>>>Не более, чем исключение.
L>>>О майн готт. Не знаю, смеяться или плакать.
BFE>>Я вижу одни эмоции без аргументов. Если вы можете обнаружить deadlock в момент исполнения, то он является одной из исключительных ситуаций.
L>Видимо, придется плакать.
L>Обнаруживать дедлок в момент исполнения уже поздно. Как в моем примере с однопутной железной дорогой.
Вы такой эмоциональный.

L>

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

L>А если предыдущее состояние тех данных невосстановимо?
Если предыдущее состояние восстановимо, то вы уже где-то раньше сделали ошибку. Если у вас два элемента системы должны находится в согласованном состоянии и один из элементов невосстановимым, то почему эти два элемента защищены двумя разными мютексами?

L>А если это не данные, а команда на открытие воздушного прервыателя на 300 КВ, у которого trip time под десять секунд и наработка на отказ всего несколько десятков переключений и при попытке получить его текущий статус твой тред залип? Ты хочешь послать команду на закрытие, чтобы "восстановиться и попробовать снова"? Боюсь, тебе даже не дадут забрать свои вещи из кьюбилка, если ты такое предложишь, потому что этот факап может стоить кому-то жизней, а компании — многомиллионных судебных исков.

Вы всё время ссылаетесь на runtime системы. Скажите, а в своих runtime системах вы работаете в терминах ниток обменивающихся данными или, всё же, в терминах real-time таймеров?

L>Дедлок в общем случае — не восстанавливаемая ситуация. Period.

L>Факт дедлока говорит о серьезном факапе в execution flow и рассчитывать на то, что тебе удастся откатиться, нельзя.
В общем случае, если вы пишите на C++ и не можете безопасно развернуть стек, то вы пишите с ошибками. Или у вас вокруг каждого вызова функции стоит try-catch ?

L>Еще раз — исправлять косяки проектирования в рантайме поздно. И в общем случае невозможно.

В самом деле, если у вас все данные протаскиваются через одну нитку, то исправить такой архитектурный косяк при нехватки производительности невозможно.
И каждый день — без права на ошибку...
Re[27]: Deadlock-prevention алгоритм
От: Evgeny.Panasyuk Россия  
Дата: 30.06.14 14:06
Оценка:
Здравствуйте, B0FEE664, Вы писали:

L>>>>Дедлок — по определению непредусмотренное поведение программы.

BFE>>>Не более, чем исключение.
EP>>Всё же deadlock (незапланированный) это ошибка в коде программы — то есть не исключение, а скорее assert.
BFE>Нет, это не ошибка, если такое поведение ускоряет выполнение приложения и было предусмотрено заранее.

Я же говорю про незапланированный deadlock, который в подавляющем большинстве случаев таковым и является.
Можно конечно представить некий хитрый алгоритм, который работает быстро, но иногда приводит к deadlock'у в силу своих особенностей, а не недосмотра — но это скорее исключение чем правило.
Сразу вспоминается SR-71, у которого на стоянке вытекает топливо.


EP>>Можно конечно представить некий fault tolerance, который закладывается и на такие баги кода, но имхо кидать исключение в таком случае всё равно не лучший вариант.

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

Чем же лучше? При раскрутке стэка может произойти другой deadlock, или что ещё хуже — livelock.
Для нормальной fault tolerance всё равно придётся предусматривать аварийное завершение, даже если без учёта deadlock'ов. Почему бы не использовать тот же самый механизм и для deadlock'ов, который всяко надёжней исключений, да ещё и подойдёт к livelock'ам.
Re[3]: Deadlock-prevention алгоритм
От: sokel Россия  
Дата: 30.06.14 14:14
Оценка:
Здравствуйте, Lazin, Вы писали:

L>Я позже посмотрю, сейчас работу нужно работать

L>У тебя нет гитхаб аккаунта? Можно было бы сделать форк+pull request, что бы ты появился в списке контрибьюторов.

Да аккаунт то есть, но ты сам смотри, какое у тебя видение, мне особо deadlock prevention пока не нужен, просто пулы мьютексов-рвлоков у себя давно причесать хотел.
Мне в общем обычно и multiple lock не нужен, просто блокирую объекты из коллекций по айдишнику на чтение — запись.

как то в таком вот духе:
class foo {
    typedef syncope::lock_pool<my_rwlock, 1024> lock_storage;
    typedef syncope::pool_guard_one<lock_storage, false> write_guard;
    typedef syncope::pool_guard_one<lock_storage, true> read_guard;
    friend class foo_read_accessor;
    friend class foo_read;
    friend class foo_modify;
    static lock_storage accessors;
public:
    foo() : bar_(0) {}
private:
    int bar_;
};

foo::lock_storage foo::accessors("foo sync");

class foo_read_accessor {
    friend class foo_read;
    friend class foo_modify;
private:
    foo_read_accessor(foo& obj)
        : obj_(obj)
    {}
public:
    int bar() const { return obj_.bar_; }
private:
    foo& obj_;
};

class foo_read
    : foo::read_guard
    , public foo_read_accessor
{
public:
    foo_read(foo& obj)
        : foo::read_guard(foo::accessors, obj)
        , foo_read_accessor(obj)
    {}
};

class foo_modify
    : foo::write_guard
    , public foo_read_accessor
{
public:
    foo_modify(foo& obj)
        : foo::write_guard(foo::accessors, obj)
        , foo_read_accessor(obj)
        , bar_changed_(false)
    {}
    ~foo_modify() {
        unlock();
        // process changes outside lock
        if(bar_changed_) {
            std::cout << "foo bar changed: " << foo_read(obj_).bar() << std::endl;
        }
    }
    void set_bar(int v) {
        if(v != obj_.bar_) {
            obj_.bar_ = v;
            bar_changed_ = true;
        }
    }
private:
    bool bar_changed_;
};


int main()
{
    foo f;
    foo_modify(f).set_bar(123);
    return 0;
}


Замотано всё, чтобы без блокировки ни прочитать и записать...
Кстати, в контексте пула локов полезны бывают ещё отмасштабированные по его размеру контейнеры, выбираешь по хэшу, работаешь внутри скопа без блокировок.
Re[4]: Deadlock-prevention алгоритм
От: sokel Россия  
Дата: 30.06.14 15:14
Оценка:
Здравствуйте, sokel, Вы писали:

S>Здравствуйте, Lazin, Вы писали:


Ещё пара мелочей, определение наличия rdlock через SFINAE + убрал lock_count из ф-ции lock_hash.
Re[28]: Deadlock-prevention алгоритм
От: B0FEE664  
Дата: 30.06.14 16:01
Оценка:
Здравствуйте, Evgeny.Panasyuk, Вы писали:

BFE>>Нет, это не ошибка, если такое поведение ускоряет выполнение приложения и было предусмотрено заранее.

EP>Я же говорю про незапланированный deadlock, который в подавляющем большинстве случаев таковым и является.
А что можно сказать про незапланированный deadlock? Всё. Висим. Точка. Речь о том, чтобы в принципе избежать такой ситуации.

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

EP>Чем же лучше? При раскрутке стэка может произойти другой deadlock,
Если написать некорректную обработку исключения, то ещё и не такое может произойти.

EP>или что ещё хуже — livelock.

livelock возможен, но и с ним понятно как бороться — отдавать время другим ниткам из той нитки, что deadlock обнаружила (после снятия всех блокировок). Если так действовать, то livelock возможен только при перегрузке системы. В конце-концов, частое выбрасывание исключений без отказа оборудования говорит об ошибке в архитектуре.

EP>Для нормальной fault tolerance всё равно придётся предусматривать аварийное завершение, даже если без учёта deadlock'ов. Почему бы не использовать тот же самый механизм и для deadlock'ов, который всяко надёжней исключений, да ещё и подойдёт к livelock'ам.

Это зависит от серьёзности возможных последствий и оценки стоимости. Убийство нитки не гарантирует освобождение всех ресурсов алокированных этой ниткой. Может оказаться, что такая утечка настолько незначительна, а убийство ниток столь редко, что система работает годами...
И каждый день — без права на ошибку...
Re[29]: Deadlock-prevention алгоритм
От: Evgeny.Panasyuk Россия  
Дата: 30.06.14 17:06
Оценка:
Здравствуйте, B0FEE664, Вы писали:

BFE>>>Нет, это не ошибка, если такое поведение ускоряет выполнение приложения и было предусмотрено заранее.

EP>>Я же говорю про незапланированный deadlock, который в подавляющем большинстве случаев таковым и является.
BFE>А что можно сказать про незапланированный deadlock?

Это ошибка в коде

BFE>Всё. Висим. Точка. Речь о том, чтобы в принципе избежать такой ситуации.


Избежать deadlock'а или чего?

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

EP>>Чем же лучше? При раскрутке стэка может произойти другой deadlock,
BFE>Если написать некорректную обработку исключения, то ещё и не такое может произойти.

Так мы же и так рассматриваем ситуацию, которой в корректной программе быть не должно. И соответственно раз произошёл deadlock, "то и не такое может произойти"

EP>>или что ещё хуже — livelock.

BFE>livelock возможен, но и с ним понятно как бороться — отдавать время другим ниткам из той нитки, что deadlock обнаружила (после снятия всех блокировок). Если так действовать, то livelock возможен только при перегрузке системы.

Незапланированный deadlock возможен только в коде с багом, точно также как и livelock.
Раз уж мы получили deadlock, то почему при раскрутке стэка не может вылезти livelock или ещё что-нибудь?

EP>>Для нормальной fault tolerance всё равно придётся предусматривать аварийное завершение, даже если без учёта deadlock'ов. Почему бы не использовать тот же самый механизм и для deadlock'ов, который всяко надёжней исключений, да ещё и подойдёт к livelock'ам.

BFE>Это зависит от серьёзности возможных последствий и оценки стоимости. Убийство нитки не гарантирует освобождение всех ресурсов алокированных этой ниткой. Может оказаться, что такая утечка настолько незначительна, а убийство ниток столь редко, что система работает годами...

Если требуется fault tolerance, не считая какие-то совсем тривиальные случаи, то придётся планировать аварийное завершение с освобождением всех ресурсов.
Re[29]: Deadlock-prevention алгоритм
От: SleepyDrago Украина  
Дата: 30.06.14 17:27
Оценка:
Здравствуйте, B0FEE664, Вы писали:

BFE>Здравствуйте, Evgeny.Panasyuk, Вы писали:


...
BFE>>>Всяко лучше, чем убивать подвисшие нитки извне, как это делают некоторые.
EP>>Чем же лучше? При раскрутке стэка может произойти другой deadlock,
BFE>Если написать некорректную обработку исключения, то ещё и не такое может произойти.
На моей памяти код который не удалось запустить на тестовом стенде лучше просто удалить. быстрое завершение намного проще потом лечить. Запускать этот не протестированный код пытающийся закатить все солнца назад вручную в продакшене это самоубийство.

...
EP>>Для нормальной fault tolerance всё равно придётся предусматривать аварийное завершение, даже если без учёта deadlock'ов. Почему бы не использовать тот же самый механизм и для deadlock'ов, который всяко надёжней исключений, да ещё и подойдёт к livelock'ам.
BFE>Это зависит от серьёзности возможных последствий и оценки стоимости. Убийство нитки не гарантирует освобождение всех ресурсов алокированных этой ниткой. Может оказаться, что такая утечка настолько незначительна, а убийство ниток столь редко, что система работает годами...
Решать что будет на продакшене после краха по любому надо. Электрики (с) все равно придут. Так что готовиться к terminate/power-down надо начинать изначально. Ну или весь этот fault tolerance удалять как неиспользуемый код =)
Re[26]: Deadlock-prevention алгоритм
От: B0FEE664  
Дата: 30.06.14 22:12
Оценка:
Здравствуйте, Evgeny.Panasyuk, Вы писали:

L>>>Дедлок — по определению непредусмотренное поведение программы.

BFE>>Не более, чем исключение.
EP>Всё же deadlock (незапланированный) это ошибка в коде программы — то есть не исключение, а скорее assert.
EP>Можно конечно представить некий fault tolerance, который закладывается и на такие баги кода, но имхо кидать исключение в таком случае всё равно не лучший вариант.

Может и не лучший, но вот, что поиском нашёл в стандарте:

30.4.2.2.2 unique_lock locking [thread.lock.unique.locking]
void lock();
1 Effects: pm->lock()
2 Postcondition: owns == true
3 Throws: Any exception thrown by pm->lock(). system_error if an exception is required (30.2.2).
system_error with an error condition of operation_not_permitted if pm is 0. system_error with
an error condition of resource_deadlock_would_occur if on entry owns is true.




Ну и

30.4.1.2/
6 The expression m.lock() shall be well-formed and have the following semantics:
12 Throws: system_error when an exception is required (30.2.2).
13 Error conditions:
— operation_not_permitted — if the thread does not have the privilege to perform the operation.
— resource_deadlock_would_occur — if the implementation detects that a deadlock would occur.
— device_or_resource_busy — if the mutex is already locked and blocking is not possible.



30.2.2 Exceptions [thread.req.exception]
1 Some functions described in this Clause are specified to throw exceptions of type system_error (19.5.6).
Such exceptions shall be thrown if any of the function’s error conditions is detected or a call to an operating
system or other underlying API results in an error that prevents the library function from meeting its
specifications.


Так что если пользоваться стандартом, то такие исключения надо обрабатывать.
И каждый день — без права на ошибку...
Re[27]: Deadlock-prevention алгоритм
От: Evgeny.Panasyuk Россия  
Дата: 30.06.14 23:36
Оценка:
Здравствуйте, B0FEE664, Вы писали:

EP>>Можно конечно представить некий fault tolerance, который закладывается и на такие баги кода, но имхо кидать исключение в таком случае всё равно не лучший вариант.

BFE>Может и не лучший, но вот, что поиском нашёл в стандарте:
BFE>

BFE>3 Throws: Any exception thrown by pm->lock(). system_error if an exception is required (30.2.2).
BFE>system_error with an error condition of operation_not_permitted if pm is 0. system_error with
BFE>an error condition of resource_deadlock_would_occur if on entry owns is true.

BFE>

Видел это. Какой именно была rationale — не знаю, возможно максимальная гибкость.
К слову сказать, Александр Степанов в своих лекциях
Автор: andyp
Дата: 17.07.13
рассказывал, что кто-то из членов комитета предлагал в стандартные итераторы добавить встроенные проверки и вроде даже исключениями, что-то типа итератор должен знать из какого он контейнера и т.п. — к счастью STL пошёл по другому пути.

BFE>Так что если пользоваться стандартом, то такие исключения надо обрабатывать.


Во-первых, какие-то специальные телодвижения не нужны (разве что поставить assert ) — там же в корне std::exception.
Во-вторых, опять-таки — это же явный баг в программе, если уж случилось такое, то неизвестно как там оно дальше пойдёт в разнос.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.