Re[5]: Многопоточный Observer на C++ (практика)
От: baily Россия  
Дата: 27.11.10 09:58
Оценка:
Здравствуйте, remark, Вы писали:

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


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

B>>Защелка открывается в методе Subscribe после добавление подписчика. В методе Unsubscribe она закрывается уведомителем под критической секцией.
B>>Класс подписчик в своем методе OnNotification должен вначале проверять, разрешен ли ему вызов. Если нет, то просто выходить.

R>Если он будет просто проверять в начале функции, то мы возвращаемся туда, откуда начали, — может работать нотификация уже отписанного объекта. Ровным счётом ничего не решается.


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

R>Какие ешё есть разные способы?


Каких то, отличающихся по сути, я не знаю. Везде используется идея защелки. Меняется только ее вид. В предложенном выше случае это просто целочисленный счетчик.


B>>Защелкой должен владеть подписчик. Можно просто создать обертку над подписчиком ( в принципе и умный указатель есть обертка ), который владеет и подписчиком

B>>и защелкой. В более сложном варианте можно сделать защелку более сложной, поместив туда еще и событие. При вызове OnNotification, когда защелка открыта,
B>>можно увеличивать счетчик использования защелки в начале и уменьшать в конце. А событие взводить, когда счетчик станет равным нулю. Тогда на событии можно ожидать,
B>>когда подписчик закончит обрабатывать свой OnNotification.

R>Это потенциальные дедлоки.


Решение рабочее. Дедлоков при аккуратной работе случаться не должно.
Re[6]: Многопоточный Observer на C++ (практика)
От: remark Россия http://www.1024cores.net/
Дата: 27.11.10 10:03
Оценка:
Здравствуйте, baily, Вы писали:

R>>Если он будет просто проверять в начале функции, то мы возвращаемся туда, откуда начали, — может работать нотификация уже отписанного объекта. Ровным счётом ничего не решается.


B>Я имел ввиду следующее. Надо создать класс-обертку, которая владеет и подписчиком и защелкой.

B>Она является частью имплементации класса-уведомителя. Обертка тоже имеет метод OnNotification.
B>Класс-уведомитель хранит массив таких оберток. Когда уведомитель делает рассылку, то он вызывает OnNotification обертки.
B>Внутри этого метода и проверяется состояние защелки, и только если она открыта, то вызывается OnNotification подписчика.

Проверяем состояние защелки — она открыта, начинаем выполнение OnNotification подписчика. В это время другой поток отписывает объект. Первый поток продолжает выполнение OnNotification подписчика, когда объект уже отписан. Вернулись туда, откуда начали. Ничего не решено.


1024cores — all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[6]: Многопоточный Observer на C++ (практика)
От: remark Россия http://www.1024cores.net/
Дата: 27.11.10 10:05
Оценка: :)
Здравствуйте, baily, Вы писали:

R>>Это потенциальные дедлоки.


B>Решение рабочее. Дедлоков при аккуратной работе случаться не должно.


Никаких ошибок вообще случаться не должно.


1024cores — all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[7]: Многопоточный Observer на C++ (практика)
От: remark Россия http://www.1024cores.net/
Дата: 27.11.10 10:07
Оценка:
Здравствуйте, remark, Вы писали:

R>Проверяем состояние защелки — она открыта, начинаем выполнение OnNotification подписчика. В это время другой поток отписывает объект. Первый поток продолжает выполнение OnNotification подписчика, когда объект уже отписан. Вернулись туда, откуда начали. Ничего не решено.


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


1024cores — all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[4]: Многопоточный Observer на C++ (практика)
От: jazzer Россия Skype: enerjazzer
Дата: 27.11.10 13:51
Оценка:
Здравствуйте, remark, Вы писали:

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


R>>Можно попробовать ожидать завершение текущего уведомления в функции Unsubscribe, но тогда скорей всего будут зависания при отключении.

R>>Я пока что не нашел подходящее решение с реализацией Unsubscribe, гарантирующей прекращение нотификаций после выхода.
R>>Если есть какие-то идеи по этому поводу, буду рад услышать.

R>Ещё один вариант решения — трактовать unsubscribe() не как отписку, а как старт асинхронной отписки, а завершение отписки происходит, когда объект получает вызов release(). Т.е. поток вызывает unsubscribe(), этим от говорит, что он хочет инициировать отписку; но никакой код, которы должен отработать только после завершения отписки, он ещё не вызывает. Потом (или возможно сразу) объекту поступает вызов release(), который говорит о том, что отписка завершена, и теперь уже никаких вызовов объекту точно поступать не будет, теперь можно вызывать код, который должен отработать только после завершения отписки.


R>


Я лично именно так бы и сделал, если бы сам писал.
jazzer (Skype: enerjazzer) Ночная тема для RSDN
Автор: jazzer
Дата: 26.11.09

You will always get what you always got
  If you always do  what you always did
Re[4]: Многопоточный Observer на C++ (практика)
От: TarasKo Голландия  
Дата: 28.11.10 21:29
Оценка:
gh2>1) корректно разрешите проблему безопасности исключений
gh2>2) избавитесь от связи (время жизни диспетчера) == (время, проведенное в критической секции)
gh2>3) гарантируете отсутствие утечки ресурса "объект-синхронизации" (сейчас это критическая секция)

И как я понимаю получится подмножество библиотеки boost::signals2. Signals2 удобнее ещё тем что не надо реализовывать какой-то интерфейс для создания подписчиков. Подписчиком может быть функция, метод класса или функтор, можно использовать так же bind, что очень удобно в некоторых случаях.
Re[3]: Многопоточный Observer на C++ (практика)
От: TarasKo Голландия  
Дата: 28.11.10 21:57
Оценка: +1 -1
Я очень много раз встречал отказ использовать исключения просто потому что люди не понимаю, как строит программы с обработкой ошибок на исключениях. На вопрос, в чём преимущество обработки ошибок через коды возврата, обычно некоторое время думают и говорят, мол типа один знакомый программист Вася, говорил что исключения тормозные, ну и как-то они запутывают код. Вы понимаете что такое ответ говорит лишь о том что человек не понимает исключений, не понимает как ими пользоваться, за предыдущее время работы не попытался их понять и научится ими пользоваться. И кстати если это время больше 2-х лет, то не стоит связываться с таким человеком и брать его на работу.

Лишь один раз я слышал действительно мотивированный отказ от построения обработки ошибок на исключениях, и это google code convention. Они отказываются от исключений в основном потому, что на момент написания code guidelines у них уже написано огромное количество кода с обработкой ошибок на кодах возврата. При этом перед этим идёт честное сравнение плюсов и минусов обеих подходов.
Re[7]: Многопоточный Observer на C++ (практика)
От: baily Россия  
Дата: 29.11.10 09:20
Оценка:
Здравствуйте, remark, Вы писали:

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


R>>>Если он будет просто проверять в начале функции, то мы возвращаемся туда, откуда начали, — может работать нотификация уже отписанного объекта. Ровным счётом ничего не решается.


B>>Я имел ввиду следующее. Надо создать класс-обертку, которая владеет и подписчиком и защелкой.

B>>Она является частью имплементации класса-уведомителя. Обертка тоже имеет метод OnNotification.
B>>Класс-уведомитель хранит массив таких оберток. Когда уведомитель делает рассылку, то он вызывает OnNotification обертки.
B>>Внутри этого метода и проверяется состояние защелки, и только если она открыта, то вызывается OnNotification подписчика.

R>Проверяем состояние защелки — она открыта, начинаем выполнение OnNotification подписчика. В это время другой поток отписывает объект. Первый поток продолжает выполнение OnNotification подписчика, когда объект уже отписан. Вернулись туда, откуда начали. Ничего не решено.


R>


Гм! Согласен. Я поторопился. У меня в коде решение, использующее ту же идею, что у вас в этом
Автор: remark
Дата: 27.11.10
посте. А именно, отписка не происходит, до тех пор, пока не уйдут все лочки с подписчика. Лочка заводится при начале каждой нотификации.
Re[4]: Многопоточный Observer на C++ (практика)
От: COFF  
Дата: 30.11.10 14:55
Оценка:
Здравствуйте, TarasKo, Вы писали:

TK>Лишь один раз я слышал действительно мотивированный отказ от построения обработки ошибок на исключениях, и это google code convention. Они отказываются от исключений в основном потому, что на момент написания code guidelines у них уже написано огромное количество кода с обработкой ошибок на кодах возврата. При этом перед этим идёт честное сравнение плюсов и минусов обеих подходов.


Android NDK, например, не поддерживает исключения и RTTI. Во что превращается портирование кода в случае, если ты их используешь, думаю объяснять не надо ))
Re[5]: Молодняк металла
От: alexeiz  
Дата: 30.11.10 16:55
Оценка: +1
Здравствуйте, COFF, Вы писали:

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


TK>>Лишь один раз я слышал действительно мотивированный отказ от построения обработки ошибок на исключениях, и это google code convention. Они отказываются от исключений в основном потому, что на момент написания code guidelines у них уже написано огромное количество кода с обработкой ошибок на кодах возврата. При этом перед этим идёт честное сравнение плюсов и минусов обеих подходов.


COF>Android NDK, например, не поддерживает исключения и RTTI. Во что превращается портирование кода в случае, если ты их используешь, думаю объяснять не надо ))


Исключения там не поддерживаются, потому что в Google их не используют. А не используют, потому что coding conventions такие. Иначе бы давно сделали. Это не так уж и сложно, как показывает следующий проект: http://www.crystax.net/android/ndk-r4.php
Re[6]: Молодняк металла
От: COFF  
Дата: 30.11.10 19:45
Оценка: +1
Здравствуйте, alexeiz, Вы писали:

COF>>Android NDK, например, не поддерживает исключения и RTTI. Во что превращается портирование кода в случае, если ты их используешь, думаю объяснять не надо ))


A>Исключения там не поддерживаются, потому что в Google их не используют. А не используют, потому что coding conventions такие. Иначе бы давно сделали. Это не так уж и сложно, как показывает следующий проект: http://www.crystax.net/android/ndk-r4.php


Это другой вопрос, на самом деле — почему это так? Если ты не гугл, конечно )) Факт, что на настоящий момент код с исключениями значительно менее портабелен, как это ни прискорбно
Re[2]: Многопоточный Observer на C++ (практика)
От: Feonyf  
Дата: 30.11.10 20:27
Оценка:
Здравствуйте, LeonCrew, Вы писали:

LC>Минусы:

LC>- дополнительный расход памяти на дополнительные списки (к каким издателям подписан подписчик), для встраиваемых систем может быть критично;

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

Поэтому просто делюсь идеей.
Моя строка построения буста:
.\bjam link=static threading=multi runtime-link=static -j %NUMBER_OF_PROCESSORS% --with-filesystem --with-thread --with-date_time address-model=64
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.