
Antony
21.02.2018
20:18:42
pragma once показывает на ряде компиляторов большую производительность, чем include guards. Другими словами - для того, чтобы ваш код препроцессировался быстрее

fox.cpp
21.02.2018
20:20:50
Люблю буст.

Google

Antony
21.02.2018
20:21:03

Berkus
21.02.2018
20:21:25

Antony
21.02.2018
20:23:09

Square
21.02.2018
20:26:35

Berkus
21.02.2018
20:27:07

Square
21.02.2018
20:27:39

Alex Фэils?︙
21.02.2018
20:31:14

Antony
21.02.2018
20:31:59
Придётся ставить старенький буст

Berkus
21.02.2018
20:32:15
^ реквестирую ревью внимательными глазами
я три дня с ним уже ебусь и чот силы кончились


Constantine
21.02.2018
20:44:31
У меня есть многопоточный код, я хочу в тестах покрутить-повертеть, что будет в разных вариантах порядка выполнения операций.
Я собираюсь решать это следующим образом: в код выполнения каждого потока я включаю некоторые вызовы, однозначно идентифицирующие место в коде, после чего включить отладочную среду, в рамках которой прохождение этих мест будет синхронизироваться и пропускаться так, как я скажу.
Вопрос А: все уже сделано до меня?
Вопрос Б: я правильно понимаю, что я беру mutex+condition_variable, беру DAG порядка выполнения, после чего узловая точка локает мутекс, записывает что достигнута в DAG, отпускает мутекс, вызывает notify_all, снова локает мутекс и вызывает wait на достижение всех предыдущих узловых в DAG?

Google

Square
21.02.2018
20:47:22
У меня есть многопоточный код, я хочу в тестах покрутить-повертеть, что будет в разных вариантах порядка выполнения операций.
Я собираюсь решать это следующим образом: в код выполнения каждого потока я включаю некоторые вызовы, однозначно идентифицирующие место в коде, после чего включить отладочную среду, в рамках которой прохождение этих мест будет синхронизироваться и пропускаться так, как я скажу.
Вопрос А: все уже сделано до меня?
Вопрос Б: я правильно понимаю, что я беру mutex+condition_variable, беру DAG порядка выполнения, после чего узловая точка локает мутекс, записывает что достигнута в DAG, отпускает мутекс, вызывает notify_all, снова локает мутекс и вызывает wait на достижение всех предыдущих узловых в DAG?
Для тестов многопоточного кода возьми relacy или ему подобное

Constantine
21.02.2018
20:50:34

Antony
21.02.2018
20:52:12
^ реквестирую ревью внимательными глазами
Я заметил потенциальный дедлок:
Вот тут вызывается под локом метод, который лочит мьютекс WaitInfo https://gist.github.com/berkus/fddcd55b865e1c24f48009cf380cd992#file-notificationqueue-h-L169
А вот тут https://gist.github.com/berkus/fddcd55b865e1c24f48009cf380cd992#file-notificationqueue-h-L151 сначала лочится WaitInfo, а потом лочится основной мьютекс

Arseny
21.02.2018
20:52:25

Antony
21.02.2018
20:52:25
А вот утечку не нашёл

Berkus
21.02.2018
20:52:57
А вот утечку не нашёл
волшебным образом умудряется читать из unique_ptr который внутри WaitInfo после того как WaitInto удалился
придется почитать ассемблер еще, т.к. при -O0 всё работает, при -O1 падает к хуям

Arseny
21.02.2018
20:55:22
Точно?
The iterator first does not need to be dereferenceable if first==last: erasing an empty range is a no-op.

Berkus
21.02.2018
20:55:47
спасибо, возможно тут и порылась проблема

Antony
21.02.2018
20:58:08

Constantine
21.02.2018
20:58:27
я плохо понимаю, кто его удалил из очереди

Berkus
21.02.2018
21:00:07

Constantine
21.02.2018
21:00:56

Berkus
21.02.2018
21:01:12
этот WaitInfo вообще можно на стеке аллоцировать, что я подумываю сделать чтобы в кучу не ходить лишний раз

Constantine
21.02.2018
21:03:17
а, я понял

Google

Constantine
21.02.2018
21:03:38
там окончание ожидания гарантирует, что он не в очереди

Berkus
21.02.2018
21:04:34
да

Constantine
21.02.2018
21:07:35
ну да, а во второй ветке, конечно, ошибка в случае таймаута

Antony
21.02.2018
21:10:37
^ реквестирую ревью внимательными глазами
Там точно дедлок:
Поток 1 наичанает выполнять эту строчку https://gist.github.com/berkus/fddcd55b865e1c24f48009cf380cd992#file-notificationqueue-h-L155
Поток 2 вызывает https://gist.github.com/berkus/fddcd55b865e1c24f48009cf380cd992#file-notificationqueue-h-L169
итого
поток 1 держит waiting->cond_mutex_ и пытается залочить mutex_
поток 2 держит mutex_ и пытаетсчя залочить waiting->cond_mutex_

Berkus
21.02.2018
21:12:11

Constantine
21.02.2018
21:15:28
после чего через atomic выбирать из них элемент и если ты выбираешь 16, то блокируешься и подбираешь следующие 16 из дека
видимо, тебе еще будет нужна переменная с текущим состоянием "есть задачи, есть исполнители, нет ничего"

Berkus
21.02.2018
21:42:13

Constantine
21.02.2018
21:42:30
ну это зависит от
вообще я там выше постил вопрос про таймлайнилку
кажется, если ты разблокируешь waiting->cond_mutex_ до блокировки основного mutex_, тебе приедет параллельный поток с задачей и выдаст

Constantine
21.02.2018
21:46:29
т.е. там нужна будет еще проверка, что задачу не кикнули

Berkus
21.02.2018
21:46:34
пока что я ничего не пони
только обнови гист а то там номера строк съедут


Constantine
21.02.2018
21:51:03
поясни как Полухин, ссылками и таймлайном
смотри,
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
21.02.2018
21:52:35
но если он ее прошел - то всё ок же

Constantine
21.02.2018
21:52:56
вроде как да

Berkus
21.02.2018
21:53:19
дальше я залочу мьютекс очереди и выдерну из waiting положенный туда value ничего не потеряв

Google

Constantine
21.02.2018
21:54:13
да, но ты должен перепроверить ready_ и выбрасывать ожидающего только если false

Berkus
21.02.2018
21:54:32
почему?
мне положили значение, я его забрал и успешно ушел

Admin
ERROR: S client not available

Constantine
21.02.2018
21:55:23
да, но в этом случае объект не находится в очереди ожидания

Berkus
21.02.2018
21:55:36
находится
он удалится после выполнения
//разблокировать waiting->cond_mutex_
std::lock_guard<std::mutex> lock(mutex_);

Constantine
21.02.2018
21:55:56
вот этот поток вытащил его
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
21.02.2018
21:56:08
ммм
так абажжи, то что он его вытащил из очереди, не значит что он там не находится - находился на момент вытаскивания и этого достаточно - он никуда уже не убежит

Constantine
21.02.2018
21:56:51
вообще если ты видишь ready_, то объекта точно нет в waitQueue_

Berkus
21.02.2018
21:57:04
а это и не обязательно

Constantine
21.02.2018
21:57:11
да, все в порядке
{
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);
}
}
что-то такое
у тебя точная эквивалентность "!ready_ под блокировкой означает присутствие в очереди"
и да, кажется, ready_ не обязательно делать atomic

Berkus
21.02.2018
22:10:28
она под мьютексом меняется, но барьер неплохо бы

Constantine
21.02.2018
22:11:07
на cppreference есть прямо примеры, когда переменная для condition variable не atomic
я верю этим ребятам)

Google

Berkus
21.02.2018
22:13:26
ага

Dmitrii
22.02.2018
01:30:59
ребят такой вопрос кто как код документирует и какие системы генерации документации сейчас самые актуальные и популярные в C++ проектах? пока что Doxygen кажется наиболее подходящим.

Aidar
22.02.2018
04:59:46

Alexandr
22.02.2018
05:04:11
А кто-то с движком Atomic Game Engine работал? Хочу через некоторое время перейти на него с Юнити. В официальном комьюнити уже зарегался, но ещё не освоился.

Yaroslav
22.02.2018
06:02:34
А в чем его прикол? Впервые слышу, прост.

Alexandr
22.02.2018
06:04:37
Это форк от Урхо3Д. Один из двух форков с возможностью написания игрового кода на C#. Ну и полностью свободный код движка.
В целом движок сам по себе не плох, но и не выдающийся. Чую, придётся искать решение для поднятия уровня графики.

Yaroslav
22.02.2018
06:05:15
А анриал енджейн?
Или не подходит? Вроде бы тоже не плох и поддкржка была от VS

Alexandr
22.02.2018
06:08:20
1. Там же нет Си-шарп вроде. Я С++ только начал изучать.
2. Я перехожу в этом плане на опенсорс как на второй рабочий движок. В качестве условно-бесплатного остаюсь на Юнити.
3. Не думаю, что у меня сейчас есть возможность использовать графические фичи Анриала. А кроме них лично для себя плюсов сейчас не вижу.

Yaroslav
22.02.2018
06:10:11
Насчкт шарпов хз, но вроде бы были. Потом загуглю, када домв буду

Alexandr
22.02.2018
06:12:09
Ой, а вопросы по его установке через консоль не будут считаться здесь флудом?
Я один раз устанавливал, но напутал с настройками. Буду устанавливать ещё раз как закончу текущие дела.
Основу я вкурил, но пара деталей остались непонятными.

/dev
22.02.2018
06:28:54