Комментарии 16
Спасибо, пусть будет больше годных статей, особенно на фоне пиццот топиков «Какое дерьмо этот ваш С++»
+9
разве драйвера пишут на плюсах? (это я по поводу последнего абзаца вступления)
0
Цель данной стати — обратить внимание разработчиков на проблемы, с которыми можно столкнуться при создании многопоточных приложений. Выявить подводные камни в реализации коммуникации между компонентами в многопоточном приложении.
по этому поводу имею сказать вот что — libdispatch.macosforge.org/
-1
Ну вот не надоело, а? Давайте сравним хотя бы с ConcRT, который появился раньше «пафосно-революционного» GCD.
Каким образом обеспечивается интероп GCD «блоков» со стандартными C++0x лямбдами (и, соответственно, std::tr1::function)?
Каким образом осуществляется контроль захвата свободных переменных (по ссылке/значению). Если Вы справились с этим вопросом, то каким образом можно сделать смешанный захват: например, захватить POD-типы по значению, а объекты — по ссылке?
Каким образом можно влиять на кеш-локальность (могу ли я явно сгруппировать блоки таким образом, чтобы блоки в одной группе получали преимущество при выборе следующего)
И это я еще даже не начинал про те же PPL (где parallel_foreach?) не говоря уж об asynchronous agents, которые реализуют РОВНО то, что описано в посте гибко, расширяемо, эффективно — на революционном GCD это все придется реализовывать самому.
Каким образом обеспечивается интероп GCD «блоков» со стандартными C++0x лямбдами (и, соответственно, std::tr1::function)?
Каким образом осуществляется контроль захвата свободных переменных (по ссылке/значению). Если Вы справились с этим вопросом, то каким образом можно сделать смешанный захват: например, захватить POD-типы по значению, а объекты — по ссылке?
Каким образом можно влиять на кеш-локальность (могу ли я явно сгруппировать блоки таким образом, чтобы блоки в одной группе получали преимущество при выборе следующего)
И это я еще даже не начинал про те же PPL (где parallel_foreach?) не говоря уж об asynchronous agents, которые реализуют РОВНО то, что описано в посте гибко, расширяемо, эффективно — на революционном GCD это все придется реализовывать самому.
+1
НЛО прилетело и опубликовало эту надпись здесь
Конструктивная критика только приветствуется :)
0
> typedef unsigned __int64 SubscriberId;
uintptr_t
>… однопоточный вариант кода…
Пока вы писали линейный поиск шесть раз, вам в голову не пришло хранить вектор отсортированным?
>… танцы с бубном вокруг вектора, чтобы и было потокобезопасно, и не очень тормозило
Поздравляю, вы изобрели read/write lock! Читайте:
en.wikipedia.org/wiki/Readers-writers_problem
en.wikipedia.org/wiki/Read/write_lock_pattern
boost::shared_mutex
uintptr_t
>… однопоточный вариант кода…
Пока вы писали линейный поиск шесть раз, вам в голову не пришло хранить вектор отсортированным?
>… танцы с бубном вокруг вектора, чтобы и было потокобезопасно, и не очень тормозило
Поздравляю, вы изобрели read/write lock! Читайте:
en.wikipedia.org/wiki/Readers-writers_problem
en.wikipedia.org/wiki/Read/write_lock_pattern
boost::shared_mutex
+1
>>uintptr_t
Не особо критично, но пожалуй (хотел было заменить на что-то типа size_t, но решил оставить так).
>>Пока вы писали линейный поиск шесть раз, вам в голову не пришло хранить вектор отсортированным?
Тони Хоар впервые произнёс, а Дональд Кнут впоследствии часто повторял известное высказывание:
«Преждевременная оптимизация — это корень всех бед».
Википедия — Оптимизация
>>Поздравляю, вы изобрели read/write lock! Читайте:
Расскажите пожалуйста по-подробней, каким именно образом нужно применить shared_mutex
для решения проблемы с deadlock-ом в приведенном примере?
Я приводил пример с оконной процедурой, возможно получилось не особо внятно…
Функция Subscribe/Unsubscribe вызывается в обработчике оконного сообщения (например по таймеру), и при этом рабочий поток вызывает в цикле функцию Observer::SendMessage(), а реализация MessageHandler() шлет окну сообщение, к примеру даже WM_SETTEXT.
В общем получается что-то вроде этого:
Не особо критично, но пожалуй (хотел было заменить на что-то типа size_t, но решил оставить так).
>>Пока вы писали линейный поиск шесть раз, вам в голову не пришло хранить вектор отсортированным?
Тони Хоар впервые произнёс, а Дональд Кнут впоследствии часто повторял известное высказывание:
«Преждевременная оптимизация — это корень всех бед».
Википедия — Оптимизация
>>Поздравляю, вы изобрели read/write lock! Читайте:
Расскажите пожалуйста по-подробней, каким именно образом нужно применить shared_mutex
для решения проблемы с deadlock-ом в приведенном примере?
Я приводил пример с оконной процедурой, возможно получилось не особо внятно…
Функция Subscribe/Unsubscribe вызывается в обработчике оконного сообщения (например по таймеру), и при этом рабочий поток вызывает в цикле функцию Observer::SendMessage(), а реализация MessageHandler() шлет окну сообщение, к примеру даже WM_SETTEXT.
В общем получается что-то вроде этого:
Observer::CDispatcher g_Dispatcher;
DWORD WINAPI WorkingThread(PVOID)
{
for(;;)
{
g_Dispatcher.SendMessage(NULL);
}
return 0;
}
...
class CMainDlg : public Observer::CSubscriber
{
private:
bool m_bSubscribed;
public:
//Subscriber interface
virtual void MessageHandler(void* pContext)
{
SetWindowText(L"Deadlock test");
}
LRESULT OnTimer(UINT, WPARAM, LPARAM, BOOL& bHandled)
{
if(m_bSubscribed)
{
g_Dispatcher.Unsubscribe(this->GetSubscriberId());
m_bSubscribed = false;
}
else
{
g_Dispatcher.Subscribe(this);
m_bSubscribed = true;
}
bHandled = TRUE;
return 0;
}
LRESULT OnInitDialog(UINT, WPARAM, LPARAM, BOOL&)
{
m_bSubscribed = false;
::CreateThread(NULL, 0, WorkingThread, NULL, 0, NULL);
SetTimer(0, 1);
...
}
...
}
0
> «Преждевременная оптимизация — это корень всех бед».
Я согласен в целом. Но только в случае когда оптимизация от O(N) до O(logN) достигается заменой велосипедного линейного поиска на вызов std::binary_search.
> Расскажите пожалуйста по-подробней, каким именно образом нужно применить shared_mutex
для решения проблемы с deadlock-ом в приведенном примере?
Всё, вопрос про reader/writer lock снят. Во втором варианте я увидел, что вы копируете весь вектор. Потом вы поменяли копирование вектора на копирование shared_ptr указателя на вектор, а я не заметил. Это вполне допустимо.
Я согласен в целом. Но только в случае когда оптимизация от O(N) до O(logN) достигается заменой велосипедного линейного поиска на вызов std::binary_search.
> Расскажите пожалуйста по-подробней, каким именно образом нужно применить shared_mutex
для решения проблемы с deadlock-ом в приведенном примере?
Всё, вопрос про reader/writer lock снят. Во втором варианте я увидел, что вы копируете весь вектор. Потом вы поменяли копирование вектора на копирование shared_ptr указателя на вектор, а я не заметил. Это вполне допустимо.
0
Недавно думал, где место UML диаграммам, как раз здесь уместно было привести поведенческие диаграммы помимо кучи кода.
+2
НЛО прилетело и опубликовало эту надпись здесь
Я ни в коем случае не имел в виду не использовать Signals2, используйте на здоровье!
Если мне понадобится счетчик ссылок, поверье, я смогу его реализовать без использования boost, просто так было удобнее пример писать :)
CreateThread используется лишь в коде для тестирования основных классов.
Данный код служит для показа основной идеи, перед повторным использованием его необходимо осмыслить и переписать заново, а также подстроить под конкретный случай.
Если мне понадобится счетчик ссылок, поверье, я смогу его реализовать без использования boost, просто так было удобнее пример писать :)
CreateThread используется лишь в коде для тестирования основных классов.
Данный код служит для показа основной идеи, перед повторным использованием его необходимо осмыслить и переписать заново, а также подстроить под конкретный случай.
0
0
Зарегистрируйтесь на Хабре, чтобы оставить комментарий
Многопоточный Observer на С++ (практика)