Berkus
только обнови гист а то там номера строк съедут
Constantine
поясни как Полухин, ссылками и таймлайном
смотри, if (waiting->cond_.wait_for(cond_lock, timeout, [waiting] { return waiting->ready_.load(); })) { v = std::move(waiting->value_); } else { //разблокировать waiting->cond_mutex_ std::lock_guard<std::mutex> lock(mutex_); если перед выполнением этой блокировки ты разблокируешь waiting->cond_mutex_, то принципиально параллельный поток проходит полностью ветку void enqueue(DataType&& v) { enqueueWaitingLocked(std::move(item)); void enqueueWaitingLocked(value_type&& v) { waiting->signal_value(std::move(v)); void signal_value(value_type&& v) { std::unique_lock<std::mutex> lock(cond_mutex_); value_ = std::move(v); ready_ = true; cond_.notify_one(); } без блокировки, так что как минимум в этом случае тебе надо еще раз проверить, что параллельный поток не выдал тебе задачу после таймаута
Berkus
но если он ее прошел - то всё ок же
Constantine
вроде как да
Berkus
дальше я залочу мьютекс очереди и выдерну из waiting положенный туда value ничего не потеряв
Constantine
да, но ты должен перепроверить ready_ и выбрасывать ожидающего только если false
Berkus
почему?
Berkus
мне положили значение, я его забрал и успешно ушел
Constantine
да, но в этом случае объект не находится в очереди ожидания
Berkus
находится
Berkus
он удалится после выполнения //разблокировать waiting->cond_mutex_ std::lock_guard<std::mutex> lock(mutex_);
Constantine
вот этот поток вытащил его void enqueue(DataType&& v) { enqueueWaitingLocked(std::move(item)); void enqueueWaitingLocked(value_type&& v) { waitQueue_.pop_front(); //вот здесь waiting->signal_value(std::move(v)); void signal_value(value_type&& v) { std::unique_lock<std::mutex> lock(cond_mutex_); value_ = std::move(v); ready_ = true; cond_.notify_one(); }
Berkus
ммм
Berkus
так абажжи, то что он его вытащил из очереди, не значит что он там не находится - находился на момент вытаскивания и этого достаточно - он никуда уже не убежит
Constantine
вообще если ты видишь ready_, то объекта точно нет в waitQueue_
Berkus
а это и не обязательно
Constantine
да, все в порядке
Constantine
{ std::unique_lock<std::mutex> cond_lock(waiting->cond_mutex_); if (waiting->cond_.wait_for(cond_lock, timeout, [waiting] { return waiting->ready_.load(); })) v = std::move(waiting->value_); } if (v == nullptr) { std::lock_guard<std::mutex> lock(mutex_); v = std::move(waiting->value_); if (!waiting->ready_) { auto it = std::find(waitQueue_.begin(), waitQueue_.end(), waiting); waitQueue_.erase(it); } }
Constantine
что-то такое
Constantine
у тебя точная эквивалентность "!ready_ под блокировкой означает присутствие в очереди"
Constantine
и да, кажется, ready_ не обязательно делать atomic
Berkus
она под мьютексом меняется, но барьер неплохо бы
Constantine
на cppreference есть прямо примеры, когда переменная для condition variable не atomic
Constantine
я верю этим ребятам)
Berkus
ага
DZ
ребят такой вопрос кто как код документирует и какие системы генерации документации сейчас самые актуальные и популярные в C++ проектах? пока что Doxygen кажется наиболее подходящим.
Aidar
она под мьютексом меняется, но барьер неплохо бы
Лок мьютекса это инвалидация ваще всего
Плодове ягідне вино
А кто-то с движком Atomic Game Engine работал? Хочу через некоторое время перейти на него с Юнити. В официальном комьюнити уже зарегался, но ещё не освоился.
Anonymous
А в чем его прикол? Впервые слышу, прост.
Плодове ягідне вино
Это форк от Урхо3Д. Один из двух форков с возможностью написания игрового кода на C#. Ну и полностью свободный код движка. В целом движок сам по себе не плох, но и не выдающийся. Чую, придётся искать решение для поднятия уровня графики.
Anonymous
А анриал енджейн?
Anonymous
Или не подходит? Вроде бы тоже не плох и поддкржка была от VS
Плодове ягідне вино
1. Там же нет Си-шарп вроде. Я С++ только начал изучать. 2. Я перехожу в этом плане на опенсорс как на второй рабочий движок. В качестве условно-бесплатного остаюсь на Юнити. 3. Не думаю, что у меня сейчас есть возможность использовать графические фичи Анриала. А кроме них лично для себя плюсов сейчас не вижу.
Anonymous
Насчкт шарпов хз, но вроде бы были. Потом загуглю, када домв буду
Плодове ягідне вино
Ой, а вопросы по его установке через консоль не будут считаться здесь флудом? Я один раз устанавливал, но напутал с настройками. Буду устанавливать ещё раз как закончу текущие дела. Основу я вкурил, но пара деталей остались непонятными.
Плодове ягідне вино
Благодарю, извиняюсь за свой косяк
🐙 Antony
она под мьютексом меняется, но барьер неплохо бы
Залочивание мьютекса - это acquire барьер, разлочивание - release барьер Так что никаких лишних барьеров городить не надо
Berkus
Залочивание мьютекса - это acquire барьер, разлочивание - release барьер Так что никаких лишних барьеров городить не надо
но всё таки я гляжу в сторону портануть это на ту очередь которую я вчера предложил положить в буст, т.к. она вроде бы адекватная
🐙 Antony
но всё таки я гляжу в сторону портануть это на ту очередь которую я вчера предложил положить в буст, т.к. она вроде бы адекватная
Пара хитростей из мастер класса о том как сделать вашу очередь более отзывчивой/быстрой: * зовите notify() не под локом - это сэкономит несколько переключаений контекста и улучшит отзывчивость * вместо деки для waitQueue используйте интрузивный список (сделайте WaitInfo классом, с указателем на след WaitInfo и у вас получится односвязный список) - сможете избежать динамических аллокаций * Напомните, чем вас не устраивает более простой вариант: https://github.com/apolukhin/Boost-Cookbook/blob/second_edition/Chapter05/04_work_queue/main.cpp#L7-L46 ?
Max
Можно ли замокать Q_OBJECT гугловским gmock-ом?
Pepe 🐸
Если есть вектор, и дано 8 тредов допустим. И мы делаем так что треды обрабатывают следующий свободный элемент, например 1й тред обрабатывает 1й, 2й -- 2й, а после освобождения, первый тред берет например 9й элемент, 2й -- 10й. Как такое правильно организуется? И лучше ли сделать если просто разбить вектор на 8 сегментов, и каждый обработать в каждом треде.
Berkus
просто в воркер треде берешь for (int i = 0; i < SOME_VALUE; ++i) { process(vector[i*8]); }
🐙 Antony
в частности в этой work_queue нету try_pop_task_for(ms)
вы мне подкинули идею. Надо мне сделать репозиторий с наборами готовых С++11 решений по самым популярным вопросам: * многопоточная очередь * как форсить rvalue, вместо perfect forwarding * case insensitive string/string_view * slab_allocator * private constructors + static shared_ptr crete() * circular_iterator * using heterogenous_map = std::map * fallback overload + specializations без enable_if * interruptable thread * coroutines ts: корутина, взаимодействующая с многопоточной очередью * boost: asserts with stacktrace * boost: simple spirit example * boost: graph parsing * ...
🐙 Antony
Да там большинство вопросов в с++11 решаются без проблем. C++17 фишки тоже можно закинуть
🐙 Antony
Да, только с кодом и попрактичнее
Berkus
Arseny
в частности в этой work_queue нету try_pop_task_for(ms)
Это-то как раз просто добавляется. А вот зачем использовать отдельную condition_variable на каждый pop?
Berkus
Это-то как раз просто добавляется. А вот зачем использовать отдельную condition_variable на каждый pop?
Кто-то тут гордился поко - это вот к вопросу о говнокоде https://github.com/pocoproject/poco/blob/develop/Foundation/src/NotificationQueue.cpp#L103
Berkus
у меня тут задача выкинуть поко из проекта, и в одной слабоподдерживаемой либе завалялся этот нотификейшен кью, я просто портанул его с поко максимально прямолинейно
Berkus
Да там большинство вопросов в с++11 решаются без проблем. C++17 фишки тоже можно закинуть
Кстати, вопрос, а что вот с этой либой? http://htmlpreview.github.io/?https://github.com/henry-ch/asynchronous/blob/master/libs/asynchronous/doc/asynchronous.html она будет куда-то двигаться?
🐙 Antony
я её вижу в первый раз :)
Anton
Мужчины, а посоветуйте годный быстрый rwlock aka shared_mutex на c++11
Anton
Я так и думал...
Berkus
бот?
Anton
А как решить тогда такую задачку - есть куча читателей которые постоянно читают и есть один писатель который пишет крайне редко буквально раз в минуту и реже, читатели читают каждые 30ms...
Berkus
spmc... хмм
Anton
Сейчас системный рвлок стоит
Berkus
там вариантов чот многа
Berkus
http://moodycamel.com/blog/2014/detailed-design-of-a-lock-free-queue вот например чел который вчера всплывал
Berkus
> Then there's a small base class for the two types of internal SPMC producer queues (one for explicit producers that holds onto memory but attempts to be faster, and one for implicit ones which attempt to recycle more memory back into the parent but is a little slower) https://github.com/cameron314/concurrentqueue