Pull to refresh

Comments 16

Спасибо, пусть будет больше годных статей, особенно на фоне пиццот топиков «Какое дерьмо этот ваш С++»
разве драйвера пишут на плюсах? (это я по поводу последнего абзаца вступления)
Цель данной стати — обратить внимание разработчиков на проблемы, с которыми можно столкнуться при создании многопоточных приложений. Выявить подводные камни в реализации коммуникации между компонентами в многопоточном приложении.


по этому поводу имею сказать вот что — libdispatch.macosforge.org/
Ну вот не надоело, а? Давайте сравним хотя бы с ConcRT, который появился раньше «пафосно-революционного» GCD.
Каким образом обеспечивается интероп GCD «блоков» со стандартными C++0x лямбдами (и, соответственно, std::tr1::function)?
Каким образом осуществляется контроль захвата свободных переменных (по ссылке/значению). Если Вы справились с этим вопросом, то каким образом можно сделать смешанный захват: например, захватить POD-типы по значению, а объекты — по ссылке?
Каким образом можно влиять на кеш-локальность (могу ли я явно сгруппировать блоки таким образом, чтобы блоки в одной группе получали преимущество при выборе следующего)

И это я еще даже не начинал про те же PPL (где parallel_foreach?) не говоря уж об asynchronous agents, которые реализуют РОВНО то, что описано в посте гибко, расширяемо, эффективно — на революционном GCD это все придется реализовывать самому.
UFO just landed and posted this here
Конструктивная критика только приветствуется :)
> 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
Не особо критично, но пожалуй (хотел было заменить на что-то типа 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);
        ...
    }
...
}

> «Преждевременная оптимизация — это корень всех бед».

Я согласен в целом. Но только в случае когда оптимизация от O(N) до O(logN) достигается заменой велосипедного линейного поиска на вызов std::binary_search.

> Расскажите пожалуйста по-подробней, каким именно образом нужно применить shared_mutex
для решения проблемы с deadlock-ом в приведенном примере?

Всё, вопрос про reader/writer lock снят. Во втором варианте я увидел, что вы копируете весь вектор. Потом вы поменяли копирование вектора на копирование shared_ptr указателя на вектор, а я не заметил. Это вполне допустимо.
Недавно думал, где место UML диаграммам, как раз здесь уместно было привести поведенческие диаграммы помимо кучи кода.
К сожалению я затрудняюсь выразить логику многопоточого приложения с помощью UML.
Может кто посоветует книгу, или хотябы пример таких диаграмм, где можно было бы выражать логику синхронизации между несколькими потоками?
UFO just landed and posted this here
Я ни в коем случае не имел в виду не использовать Signals2, используйте на здоровье!
Если мне понадобится счетчик ссылок, поверье, я смогу его реализовать без использования boost, просто так было удобнее пример писать :)
CreateThread используется лишь в коде для тестирования основных классов.
Данный код служит для показа основной идеи, перед повторным использованием его необходимо осмыслить и переписать заново, а также подстроить под конкретный случай.
Sign up to leave a comment.

Articles