Описываются:
— Модель памяти (memory model)
— Атомарные операции (atomics)
— Локальные для потока переменные (thread-local static variables)
— Потоки (threads)
— Мьютексы (mutexes)
— Условные перменные (condition variables)
— Однократная инициализация (one-time initialization)
— Асинхронные операции (futures)
Так же описывается, что нас ждёт в более отдалённом будущем (в boost, будем надеятся значительно раньше):
— Пулы потоков (thread pools)
— Многопоточные контейнеры (concurrent_queue, concurrent_stack и т.д.)
— Параллельные алгоритмы (parallel_for, parallel_sort и т.д.)
— Транзакционная память и автоматическое распараллеливание (software transactional memory, auto-parallelisation)
Здравствуйте, remark, Вы писали:
R>Глядим коротко, что нас, пользователей С/С++, ждёт нового в С++0x относительно поддержки многопоточности:
а интересно, будет ли вообще С++0x ?
просто "что нас ждёт нового в С++0x" — такая басянистая фраза, что уже не помню она появилась раньше или "что нас ждёт нового в Duke Nukem Forever"
может правильно надо писать "что нас ждёт нового в С++хx" ?
Здравствуйте, Аноним, Вы писали:
R>>Глядим коротко, что нас, пользователей С/С++, ждёт нового в С++0x относительно поддержки многопоточности:
А>а интересно, будет ли вообще С++0x ?
C++09. И нииcensored.
До последнего не верил в пирамиду Лебедева.
Re[3]: [ANN] The Future of Concurrency in C++
От:
Аноним
Дата:
05.05.08 08:24
Оценка:
Здравствуйте, Roman Odaisky, Вы писали:
RO>C++09. И нииcensored.
ну да, последний шанс для стандарта 0х
а значит принимать его прийдётся в спешке
Я так понимаю, ожидания нескольких событий ( по типу WaitForMultipleObjects ) не будет ?
Здравствуйте, remark, Вы писали:
R>Глядим коротко, что нас, пользователей С/С++, ждёт нового в С++0x относительно поддержки многопоточности: R>http://www.justsoftwaresolutions.co.uk/files/future_of_concurrency.pdf
R>Описываются: R> — Модель памяти (memory model) R> — Атомарные операции (atomics) R> — Локальные для потока переменные (thread-local static variables) R> — Потоки (threads) R> — Мьютексы (mutexes) R> — Условные перменные (condition variables) R> — Однократная инициализация (one-time initialization) R> — Асинхронные операции (futures)
R>Так же описывается, что нас ждёт в более отдалённом будущем (в boost, будем надеятся значительно раньше): R> — Пулы потоков (thread pools) R> — Многопоточные контейнеры (concurrent_queue, concurrent_stack и т.д.) R> — Параллельные алгоритмы (parallel_for, parallel_sort и т.д.) R> — Транзакционная память и автоматическое распараллеливание (software transactional memory, auto-parallelisation)
Здравствуйте, Аноним, Вы писали:
А>Здравствуйте, remark, Вы писали:
R>>Глядим коротко, что нас, пользователей С/С++, ждёт нового в С++0x относительно поддержки многопоточности:
А>а интересно, будет ли вообще С++0x ? А>просто "что нас ждёт нового в С++0x" — такая басянистая фраза, что уже не помню она появилась раньше или "что нас ждёт нового в Duke Nukem Forever"
А>может правильно надо писать "что нас ждёт нового в С++хx" ?
Это ещё более басянистая фраза
Если действительно интрересно, то попробуй последить за работой WG21 — там всё открыто.
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on RSDN, USENET and in e-mail?
А как её реализовывать без поддержки ОС?
Хотя бы потому что в POSIX её нет.
Я думаю, что нет.
Здравствуйте, s.ts, Вы писали:
ST>Я так понимаю, ожидания нескольких событий ( по типу WaitForMultipleObjects ) не будет ?
ST>Здравствуйте, remark, Вы писали:
R>>Глядим коротко, что нас, пользователей С/С++, ждёт нового в С++0x относительно поддержки многопоточности: R>>http://www.justsoftwaresolutions.co.uk/files/future_of_concurrency.pdf
R>>Описываются: R>> — Модель памяти (memory model) R>> — Атомарные операции (atomics) R>> — Локальные для потока переменные (thread-local static variables) R>> — Потоки (threads) R>> — Мьютексы (mutexes) R>> — Условные перменные (condition variables) R>> — Однократная инициализация (one-time initialization) R>> — Асинхронные операции (futures)
R>>Так же описывается, что нас ждёт в более отдалённом будущем (в boost, будем надеятся значительно раньше): R>> — Пулы потоков (thread pools) R>> — Многопоточные контейнеры (concurrent_queue, concurrent_stack и т.д.) R>> — Параллельные алгоритмы (parallel_for, parallel_sort и т.д.) R>> — Транзакционная память и автоматическое распараллеливание (software transactional memory, auto-parallelisation)
А как же select?
R>Хотя бы потому что в POSIX её нет.
R>Я думаю, что нет.
ST>>Я так понимаю, ожидания нескольких событий ( по типу WaitForMultipleObjects ) не будет ?
Здравствуйте, dip_2000, Вы писали:
RO>>А как же select?
_>AFAIK, он может значительно меньше чем WFMO.
Что именно не умеет select(2) такого, что умеет WaitForMultipleObjects? (Впрочем, обе они кривые, хотя бы потому, что у них слишком сильное ограничение на количество событий.)
Здравствуйте, Roman Odaisky, Вы писали:
RO>Здравствуйте, dip_2000, Вы писали:
RO>>>А как же select?
_>>AFAIK, он может значительно меньше чем WFMO.
RO>Что именно не умеет select(2) такого, что умеет WaitForMultipleObjects? (Впрочем, обе они кривые, хотя бы потому, что у них слишком сильное ограничение на количество событий.)
Признаться не линуксоид я ни разу, но когда рассказывал линуксоидам что может WFMO они кусали локти (не надо холивара! у POSIX есть свои плюсы)
Потоков дожидаться по хендлу, процессов.
The WaitForMultipleObjects function can specify handles of any of the following object types in the lpHandles array:
Здравствуйте, dip_2000, Вы писали:
RO>>Что именно не умеет select(2) такого, что умеет WaitForMultipleObjects? (Впрочем, обе они кривые, хотя бы потому, что у них слишком сильное ограничение на количество событий.) _>Признаться не линуксоид я ни разу, но когда рассказывал линуксоидам что может WFMO они кусали локти :) (не надо холивара! у POSIX есть свои плюсы) _>Потоков дожидаться по хендлу, процессов. _>Добавлю что всех, или любого. В любых комбинациях
Понятно. Это древний флеймообразователь. Основные аргументы — «а мы вот так умеем» и «вот так — это антипаттерн».
Я считаю, что идея WFMO изначально нехороша. Как кто-то где-то сказал, мьютексы, условия и т. п. — это кровати, в которых спят потоки. А спать надлежит в одной кровати, если только речь не об экс-президенте США.
Подход WFMO — вот у меня есть событие, я его выставлю, когда произойдет что-нибудь интересное (ожидающий поток выбирает нужные ему события и блокируется).
Идеологически правильный подход — на тебе коллбек, когда что-нибудь интересное произойдет, звякни (а коллбек дернет условие на стороне ожидающего потока).
Впрочем, функция ожидания одного из многих событий тоже нужна — в ситуациях, когда нельзя/сложно напрямую договориться с генератором этих событий (например, когда они сидят в ядре). Поэтому и существует select (и более продвинутые разновидности вроде epoll и kqueue). Собственно, используя асинхронный В/В, можно даже здесь отказаться от подобных функций, но такое решение попросту сильно потеряет в эффективности.
Здравствуйте, Аноним, Вы писали:
А>Здравствуйте, Roman Odaisky, Вы писали:
RO>>C++09. И нииcensored.
А>ну да, последний шанс для стандарта 0х А>а значит принимать его прийдётся в спешке
Вообе-то есть четкий график, когда и что.
И, как жалуется Строуструп, если бы не бюрократия, которая царит в ISO, стандарты бы принимались гораздо быстрее.
По его оценкам, стандарт будет готов осенью 2008-го года (финальная версия), а потом около года проваландается по инстанциям до официального издания.
Т.е. к моменту официального выхода комитет уже год как будет работать над TR2.
Здравствуйте, Roman Odaisky, Вы писали:
RO>Я считаю, что идея WFMO изначально нехороша. Как кто-то где-то сказал, мьютексы, условия и т. п. — это кровати, в которых спят потоки. А спать надлежит в одной кровати, если только речь не об экс-президенте США.
RO>Подход WFMO — вот у меня есть событие, я его выставлю, когда произойдет что-нибудь интересное (ожидающий поток выбирает нужные ему события и блокируется). RO>Идеологически правильный подход — на тебе коллбек, когда что-нибудь интересное произойдет, звякни (а коллбек дернет условие на стороне ожидающего потока).
RO>Я считаю, что идея WFMO изначально нехороша. Как кто-то где-то сказал, мьютексы, условия и т. п. — это кровати, в которых спят потоки. А спать надлежит в одной кровати, если только речь не об экс-президенте США.
Не всё понял. Тебе не нравится то что WFMO позволяет блокироваться не только на потоках ввода-вывода, а ещё и на мьютексах, семафорах и т.п.? Или не нравится вообще подход "ждать более чем один обьект синхронизации"?
RO>Подход WFMO — вот у меня есть событие, я его выставлю, когда произойдет что-нибудь интересное (ожидающий поток выбирает нужные ему события и блокируется). RO>Идеологически правильный подход — на тебе коллбек, когда что-нибудь интересное произойдет, звякни (а коллбек дернет условие на стороне ожидающего потока).
Хм. А в чём разница? Реально в прикладном коде это всё равно будет обёрнуто в реактор (который к тому же абстрагируется от того что там под капотом — WFMO или select) который в итоге дёрнет именно коллбек с тем контекстом который с ним ассоциирован. А отдавать настоящие колбеки в функцию синхронизации... Не знаю, мне не нравится Ну или по крайней мере, не вижу явных преимуществ.
Здравствуйте, remark, Вы писали:
RO>>Подход WFMO — вот у меня есть событие, я его выставлю, когда произойдет что-нибудь интересное (ожидающий поток выбирает нужные ему события и блокируется). RO>>Идеологически правильный подход — на тебе коллбек, когда что-нибудь интересное произойдет, звякни (а коллбек дернет условие на стороне ожидающего потока).
R>А почему первый подход плохой?
(Главное) Выставляет наружу объекты синхронизации.
Сигналит даже тогда, когда никто не слушает.
Требует WaitForMultipleObjects или велосипед.
Поди разбери, что именно сработало (недостаток именно WFMO, а не подхода).
Строгие ограничения на количество объектов (недостаток именно WFMO, а не подхода).
Относительный таймаут (недостаток именно WFMO, а не подхода).
Я поискал немного по RSDN, все увиденные мной упоминания WFMO, кроме одного, были связаны с ожиданием завершения N-ного числа потоков. Хотя это то же самое, что дожидаться завершения по одному.
Приведи пример кода, который использует WaitForMultipleObjects и без него никак не обойдется.
Здравствуйте, Left2, Вы писали:
RO>>Я считаю, что идея WFMO изначально нехороша. Как кто-то где-то сказал, мьютексы, условия и т. п. — это кровати, в которых спят потоки. А спать надлежит в одной кровати, если только речь не об экс-президенте США. L>Тебе не нравится то что WFMO позволяет блокироваться не только на потоках ввода-вывода, а ещё и на мьютексах, семафорах и т.п.?
Это может не нравиться только Шеридану :-)
L>Или не нравится вообще подход "ждать более чем один обьект синхронизации"?
А вот подход, наверное, неправильный.
RO>>Подход WFMO — вот у меня есть событие, я его выставлю, когда произойдет что-нибудь интересное (ожидающий поток выбирает нужные ему события и блокируется). RO>>Идеологически правильный подход — на тебе коллбек, когда что-нибудь интересное произойдет, звякни (а коллбек дернет условие на стороне ожидающего потока). L>Хм. А в чём разница? Реально в прикладном коде это всё равно будет обёрнуто в реактор (который к тому же абстрагируется от того что там под капотом — WFMO или select) который в итоге дёрнет именно коллбек с тем контекстом который с ним ассоциирован. А отдавать настоящие колбеки в функцию синхронизации... Не знаю, мне не нравится :) Ну или по крайней мере, не вижу явных преимуществ.
Это немножко другое. select, poll, epoll, kqueue, IOCP — это демультиплексоры. Они выбирают подмножество интересных дескрипторов из (потенциально большого) множества.
Речь о (проблемном) подходе, в котором события, на которых можно блокироваться, выставляются как часть интерфейса.
L>>Хм. А в чём разница? Реально в прикладном коде это всё равно будет обёрнуто в реактор (который к тому же абстрагируется от того что там под капотом — WFMO или select) который в итоге дёрнет именно коллбек с тем контекстом который с ним ассоциирован. А отдавать настоящие колбеки в функцию синхронизации... Не знаю, мне не нравится Ну или по крайней мере, не вижу явных преимуществ.
RO>Это немножко другое. select, poll, epoll, kqueue, IOCP — это демультиплексоры. Они выбирают подмножество интересных дескрипторов из (потенциально большого) множества.
Так и WFMO — точно такой же демультиплексор, с чуть другим (даже не принципиально другим, а просто чуть другим) интерфейсом.
RO>Речь о (проблемном) подходе, в котором события, на которых можно блокироваться, выставляются как часть интерфейса.
Всё равно не пойму. При чём тут сам WFMO тогда? И что плохого в том что события выставляются как часть интерфейса? В грамотно спроектированной системе всё равно это будет в виде "вот это событие говорит о том что в очереди заданий появилось новое задание, а вот это говорит о том что нужно завершить работу и потушиться". Чем это принципиально отличается от "дёрни меня за эту функцию в случае 1, и вот за эту в случае 2"? Или я неправильно понял твою идею насчёт коллбеков?
Здравствуйте, Аноним, Вы писали:
А>Здравствуйте, Roman Odaisky, Вы писали:
RO>>C++09. И нииcensored.
А>ну да, последний шанс для стандарта 0х А>а значит принимать его прийдётся в спешке
Ну почему же, может быть ещё С++0A, C++0B, C++0xDEADBEEF в конце концов.
Нужно разобрать угил.
Re: [ANN] The Future of Concurrency in C++
От:
Аноним
Дата:
05.05.08 22:24
Оценка:
R>Так же описывается, что нас ждёт в более отдалённом будущем (в boost, будем надеятся значительно раньше): R> — Пулы потоков (thread pools)
А смысл их отделять от обычных потоков? Если уж ввели некую абстракцию самого потока, то почему бы в имплементации не делать пул потоков или юзать механизм предоставляемый ОС (намекаю на мой любимый QueueUserWorkItem)?
R> — Транзакционная память и автоматическое распараллеливание (software transactional memory, auto-parallelisation)
Второе умеет уже сейчас Intel CPP
Здравствуйте, Roman Odaisky, Вы писали:
RO>(Главное) Выставляет наружу объекты синхронизации. RO>Сигналит даже тогда, когда никто не слушает. RO>Требует WaitForMultipleObjects или велосипед. RO>Поди разбери, что именно сработало (недостаток именно WFMO, а не подхода). RO>Строгие ограничения на количество объектов (недостаток именно WFMO, а не подхода). RO>Относительный таймаут (недостаток именно WFMO, а не подхода).
RO>Я поискал немного по RSDN, все увиденные мной упоминания WFMO, кроме одного, были связаны с ожиданием завершения N-ного числа потоков. Хотя это то же самое, что дожидаться завершения по одному.
(краткий ответ на этот и предыдущий пост, ибо согласен что это флейм )
Вся прелесть(и, одновременно идеологическое зло) Что можно разом дожидаться разнородных сигналов(там выше описано каких). Позволяет существенно упростить... я бы сказал логику, и при условии что вы хорошо представляете механизмы синхронизации WinAPI это будет верно, для всех остальных случаев подойдет фраза "снизить количество строк"(хотя убить того программиста, у которого это единственная цель )
RO>Приведи пример кода, который использует WaitForMultipleObjects и без него никак не обойдется.
Разумееется такого нет Всегда можно сильно или не сильно извратиться и написать код, делающий то же самое. Но после понимания WFMO(или прожигания мозга антинаучным API, для кого как), и его использования, код становится проще, лаконечнее. Можно сказать удобнее в написании для пользователя API.
PS Я абсолютно согласен что идеологически, изначально подход был не оптимальным, и, возможно не лучшим(можно еще порассуждать про "в UNIX все файлы"). НО. То что получилось, при адекватном использовании, крайне удобно.
Здравствуйте, Аноним, Вы писали:
R>>Так же описывается, что нас ждёт в более отдалённом будущем (в boost, будем надеятся значительно раньше): R>> — Пулы потоков (thread pools)
А>А смысл их отделять от обычных потоков? Если уж ввели некую абстракцию самого потока, то почему бы в имплементации не делать пул потоков
Об этом и идёт речь. Просто одно дело, когда ты у себя в программе быстренько делаешь пул потоков на скорую руку. И другое дело, описать это формально на уровне стандарта ISO, какие у него возможности, какие к нему требования, какие он даёт гарантии и т.д. В данный момент у комитета стандартизации есть более важные вопросы — ещё модель памяти до конца не утвердили.
А>или юзать механизм предоставляемый ОС (намекаю на мой любимый QueueUserWorkItem)?
Ну типа они предполагают, что С++ будет работать ещё на паре ОС, кроме Windows.
R>> — Транзакционная память и автоматическое распараллеливание (software transactional memory, auto-parallelisation)
А>Второе умеет уже сейчас Intel CPP
У Intel есть компилятор, который и первое умеет. Только пока, по-моему, от этого никому ни жарко, ни холодно.
Здравствуйте, Left2, Вы писали:
RO>>Речь о (проблемном) подходе, в котором события, на которых можно блокироваться, выставляются как часть интерфейса. L>Всё равно не пойму. При чём тут сам WFMO тогда? И что плохого в том что события выставляются как часть интерфейса? Чем это принципиально отличается от "дёрни меня за эту функцию в случае 1, и вот за эту в случае 2"?
Во-первых, это сильно вредит портируемости.
Во-вторых, это решение задачи не с той стороны. К примеру, некий поток собирает данные и выставляет событие всякий раз, как доступна новая порция данных. Если ты хочешь обрабатывать эти данные, тебе непременно нужен другой поток, который будет блокироваться на том событии. Что же делать, если у тебя есть, к примеру, атомарная функция, в которую эти данные нужно передавать, не пытаясь кого-нибудь разбудить?
Всё красиво и аккуратно. Синхронизация только там, где нужна. Может быть сколько угодно экземпляров обоих классов. Для демонстрации ожидания двух событий я сделал флаг остановки, хотя на самом деле он не требуется — можно вызвать boost::thread::interrupt() и из ближайшей блокирующей функции вылетит исключение. Т. е., обработчик можно было переписать попросту так:
Если же собиратель данных будет выставлять наружу событие, то он должен будет, во-первых, держать у себя backlog данных, которые у него еще не забрали, во-вторых, будет обязательно будить все потоки (в то время как коллбек может принять решение, что эта порция данных ему неинтересна), в-третьих, я не уверен, но выглядит похоже на priority inversion в особо несчастных случаях.
Тем более, что в ядре всё равно где-то находится список тех, кто ожидает наступления данного события, — т. е., набор «коллбеков» всё равно есть, только спрятан! Лучше уж написать его самому так, как надо.
Извиняюсь, что опять вклиниваюсь в дискуссию
RO>Во-первых, это сильно вредит портируемости.
Есть в практике слычаи, когда не только с Винды код переезжает, а и НА нее другие системы не очень заботятся о портируемости многопоточного кода, почему здесь это приводится как минус ?
RO>Во-вторых, это решение задачи не с той стороны.
А вот скажите, с какой стороны надо решать задачу подобного плана :
есть массив структур. для каждой создается массив обработчик. функция потока получает указатель на "свою" структуру. Отрабатывает, изменяет структуру, и поток умирает. Вопрос : зачем тут плодить множество сущностей ? зачем потоку в конце жизни выставлять событие (сигнал, дергать коллбэк)?
//на глазокstruct some_mega_struct{ int i_; };
int ThreadFoo(void* pContext)
{
some_mega_struct* p = static_cast<some_mega_struct*>(pContext);
(pContext->i)++;
return 0;
}
HANDLE hVec[16];
some_mega_struct vec_some_mega_struct[16];
for (size_t i = 0; i != 16; ++i )
hVec[i] = CreateThread(...,&vec_some_mega_struct[i]);
WFMO(sizeof(hVec) ,&hVec[0],); // вот тут дождались
Здравствуйте, dip_2000, Вы писали:
RO>>Во-первых, это сильно вредит портируемости. _>Есть в практике слычаи, когда не только с Винды код переезжает, а и НА нее :) другие системы не очень заботятся о портируемости многопоточного кода, почему здесь это приводится как минус ? :xz:
Поинтересуйся как-нибудь, на скольки платформах доступны pthreads и GNU Pth. (Подсказка: «p» — это POSIX.)
RO>>Во-вторых, это решение задачи не с той стороны. _>А вот скажите, с какой стороны надо решать задачу подобного плана :
_>
_>for (size_t i = 0; i != 16; ++i )
_>hVec[i] = CreateThread(...,&vec_some_mega_struct[i]);
_>WFMO(sizeof(hVec) ,&hVec[0],); // вот тут дождались
_>
Я же специально упомянул этот случай выше по ветке.
С очень простой стороны:
for(std::thread& t : pool) // C++09
{
t.join();
}
Здесь вполне можно дождаться завершения первого, затем второго и т. д. Тем более, что с высокой вероятностью здесь будет 0—1 системных вызовов (если потоки успеют сделать свое черное дело).
Здравствуйте, Roman Odaisky, Вы писали:
RO>Здравствуйте, dip_2000, Вы писали:
RO>>>Во-первых, это сильно вредит портируемости. _>>Есть в практике слычаи, когда не только с Винды код переезжает, а и НА нее другие системы не очень заботятся о портируемости многопоточного кода, почему здесь это приводится как минус ?
RO>Поинтересуйся как-нибудь, на скольки платформах доступны pthreads и GNU Pth. (Подсказка: «p» — это POSIX.)
Какое уважение к собеседнику Спасибо, поинтересуюсь обязательно. RO>Я же специально упомянул этот случай выше по ветке. RO>С очень простой стороны: RO>
RO>Здесь вполне можно дождаться завершения первого, затем второго и т. д. Тем более, что с высокой вероятностью здесь будет 0—1 системных вызовов (если потоки успеют сделать свое черное дело).
Это уже не язык для перфоманса, имхо.... Вобщем я получил ответ
Здравствуйте, jazzer, Вы писали:
J>как жалуется Строуструп, если бы не бюрократия, которая царит в ISO, стандарты бы принимались гораздо быстрее. J>По его оценкам, стандарт будет готов осенью 2008-го года (финальная версия), а потом около года проваландается по инстанциям до официального издания. J>Т.е. к моменту официального выхода комитет уже год как будет работать над TR2.
Наверное, это даже к лучшему. Это даст время производителям компиляторов. Они смогут спокойно реализовать все фичи, выпустить пару бет, исправить баги, и торжественно выпустить новую версию вскоре после официального выхода.
Интересно, сможет ли комитет в течение того года фиксить баги, которые обнаружат многочисленные «бета-тестеры», или будет складывать их в долгий ящик^W^W^W в TR2?
RO>>Здесь вполне можно дождаться завершения первого, затем второго и т. д. Тем более, что с высокой вероятностью здесь будет 0—1 системных вызовов (если потоки успеют сделать свое черное дело). _>Это уже не язык для перфоманса, имхо.... Вобщем я получил ответ :beer:
Завершение потока — это частный случай. Хотя бы потому, что поток по определению не может сообщить наружу, что он завершился :-)
Проведи как-нибудь эксперимент:
void f(void *)
{
Sleep(100);
}
std::vector<HANDLE> pool(N);
for(std::size_t i = 0; i < N; ++i)
{
pool[i] = (HANDLE)_beginthreadex(0, 0, f, 0, 0, 0);
}
// вариант 1
WaitForMultipleObjects(N, &pool.begin(), TRUE, INFINITE);
// вариант 2for(std::size_t i = 0; i < N; ++i)
{
WaitForSingleObject(pool[i], INFINITE);
}
Что выполнится быстрее? Я уверен, что разницы во времени исполнения нет.
RO>Что выполнится быстрее? Я уверен, что разницы во времени исполнения нет.
я уверен что разницы между
++i и i++ в 98% случаев нет, и тем не менее в приличном обществе так не пишут. Думаю по понятным причинам. Код пишется не на 1 частный случай. Этот же код может работать, работать, а потом выстрелить в совершенно других условиях.
Вобщем продолжать смысла нет. Думаю все все поняли
Здравствуйте, dip_2000, Вы писали:
_>я уверен что разницы между _>++i и i++ в 98% случаев нет, и тем не менее в приличном обществе так не пишут. Думаю по понятным причинам. Код пишется не на 1 частный случай. Этот же код может работать, работать, а потом выстрелить в совершенно других условиях. _>Вобщем продолжать смысла нет. Думаю все все поняли :-)
Так вот... К чему это я?
В последнем черновике стандарта предусмотрен метод std::thread_group::join_all().
В Boost 1.35 на всех платформах он реализован как join в цикле.