- 01
- 02
- 03
- 04
- 05
- 06
- 07
- 08
- 09
- 10
- 11
- 12
- 13
- 14
- 15
static QPainterPath::ElementType qpaintengineex_line_types_16[] = {
QPainterPath::MoveToElement, QPainterPath::LineToElement,
QPainterPath::MoveToElement, QPainterPath::LineToElement,
QPainterPath::MoveToElement, QPainterPath::LineToElement,
... еще 12 строк ...
QPainterPath::MoveToElement, QPainterPath::LineToElement
};
static QPainterPath::ElementType qpaintengineex_rect4_types_32[] = {
QPainterPath::MoveToElement, QPainterPath::LineToElement, QPainterPath::LineToElement, QPainterPath::LineToElement, // 1
QPainterPath::MoveToElement, QPainterPath::LineToElement, QPainterPath::LineToElement, QPainterPath::LineToElement, // 2
... еще 29 строк ...
QPainterPath::MoveToElement, QPainterPath::LineToElement, QPainterPath::LineToElement, QPainterPath::LineToElement, // 31
QPainterPath::MoveToElement, QPainterPath::LineToElement, QPainterPath::LineToElement, QPainterPath::LineToElement, // 32
};
ctm 13.06.2012 13:35 # −5
а заведомо в 1 потоке вполне оправдано.
bormand 13.06.2012 13:39 # +4
Схуя? (Простите, других слов для ответа не нашлось).
Steve_Brown 13.06.2012 18:16 # +1
bormand 13.06.2012 19:36 # +1
ctm 14.06.2012 06:25 # 0
хотя, работа с гуи из нескольких потоков сама по себе тот еще ГК.
bormand 14.06.2012 06:42 # 0
Ну, в данном случае, их используют только для чтения...
> хотя, работа с гуи из нескольких потоков сама по себе тот еще ГК
В Qt оно и не работает. Максимум можно порисовать на QImage из соседнего потока.
ctm 14.06.2012 07:26 # +2
вот и рефлекс уже выработался %( условный.
bormand 14.06.2012 07:54 # 0
Хотя если выработать для себя список правил по написанию безопасного кода, то не все так и ужасно.
P.S. Не особо люблю потоки, мне больше нравятся процессы или асинхронная обработка, хотя, зачастую, выбора нет.
defecate-plusplus 14.06.2012 09:01 # +5
поток - друг человека
и тем лучше, когда друзей много
Steve_Brown 14.06.2012 09:52 # 0
Проблема может быть с многопоточностью, если статические переменные локальные. Но и то, для POD - маловероятно.
bormand 14.06.2012 10:08 # +1
За пределами этой модели треды выпускают свои клыки, и пытаются откусить программисту ногу.
P.S. Я не утверждаю, что опытный программист не справится с тредами, и что они абсолютное зло. Я бы, скорее, назвал их злом необходимым.
roman-kashitsyn 14.06.2012 10:20 # 0
bormand 14.06.2012 10:30 # 0
Тут ключевое слово "быстрого". Для типичного потокобезопасного кода особого опыта не нужно. Справится любой программист, который выучил простые правила.
А вот быстрый код, выходящий за рамки мутексов, очередей и семафоров, это точно черная магия, за которую без опыта лучше не браться.
roman-kashitsyn 14.06.2012 10:34 # 0
Если синкать всё подряд, от потоков будет больше вреда, чем пользы - слишком много времени будет уходить на переключение контекста. В той же Java есть неплохие стредства для работы, но если начать разбираться, как эти средства реализованы, мозг закипит довольно быстро. Да и в этих средствах, написанных настоящими профессионалами, порой находят ошибки.
bormand 14.06.2012 10:51 # 0
defecate-plusplus 14.06.2012 10:30 # −1
на дворе 2012 год, программист обязан хорошо подумать над тем, как он собирается использовать 4-6-8 ядер на пользовательской машине
и не столько уж это доставляет проблем, всего то надо выбрать удобный фреймворк
bormand 14.06.2012 10:43 # +1
defecate-plusplus 14.06.2012 10:55 # 0
в 99% случаев потоков хватает
не хочется общего адресного пространства - не пользуйся общими переменными, раз так беспокоит "черная магия" написать одну строчку boost::mutex::scoped_lock lk(mymutex_); внутри блока {} / функции
да и thread local сносно работает
когда пишешь приложение, работающее одновременно с n сетевыми подключениями, m фоновыми задачами, то выполнять все их в основном потоке (даже с помощью iocp/waitformultipleobjects) - только создавать лишние лаги для основного потока, взаимодействующего с консолью
никто не говорит о параллельном расчете обратной матрицы на 200 потоках, обыденная повседневная многопоточность не требует сверхусилий, и даже наоборот, серьезно облегчает решение проблем с отзывчивостью - есть побочные потоки, они что то вошкаются со своими задачами, когда у них готов реальный результат, они об этом просто сообщают основному потоку, который принимает решение где и когда с этим результатом работать
удобство и масштабируемость такого решение в т.ч. ложится на плечи фреймворка, и если это всё делать руками, то конечно лениво и "многопоточность - зло"
просто прошли годы, а ватсон без трубки я без asio уже не могу
roman-kashitsyn 14.06.2012 11:05 # 0
Простая задачка: есть направленный граф задач, вершины - задачи (пусть будет экземпляр runnable), рёбра - зависимости между задачами. Нужно выполнить весь граф с учётом зависимостей (т.е. запуск задачи невозможен, пока задачи-зависимости не выполнены), по максимуму используя возможность параллелезации.
Даже в такой несложной задаче одной строчкой "чёрной магии" не обойтись.
defecate-plusplus 14.06.2012 11:34 # +1
есть K задач (вершин), M потоков, ограничений на К и М не накладывается,
состояние всех задач хранится в общем массиве, к которому ко всему прочему прилагается нечто, способное сигнализировать о моменте, что состояние массива изменилось (это может быть сделано с помощью condition variable, либо с помощью коллбека как я покажу ниже)
каждая задача знает набор, от которого она зависит, и по каждой реакции на вышеописанное событие ей следует посмотреть в этот массив, способна ли она начать свою работу. если не способна - делает return из коллбека
если делать конкретно на asio, то должен быть некий master object, в котором собственно и будет храниться массив выполненности задач, и который будет самостоятельно ждать события и самостоятельно же запускать задачи на выполнение обычным myioservice_.post(...thistask...).
событие о том, что задача закончилась - состояние массива требуется изменить - просто задача последнием действием делает коллбек в мастер обжект
с таким решением количество потоков задается в параметрах командной строки и хорошо работает как на 1 потоке, так и на 100
так что фактически с помощью asio не придется писать вообще ни одного мутекса
defecate-plusplus 14.06.2012 11:42 # +1
покупайте нашу поебень
roman-kashitsyn 14.06.2012 12:08 # 0
я не уверен, но вроде бы коллбэк может быть вызван сразу из нескольких потоков, и весьма вероятно будет нужна блокировка. Если только коллбэк - это не функтор, помещаемый в очередь сообщений для "master object" и выполняемый синхронно.
bormand 14.06.2012 12:14 # 0
Имхо достаточно просто очереди сообщений с идентификатором задачи и ее результатом.
defecate-plusplus 14.06.2012 12:14 # 0
чудес ведь не бывает, т.е. внутри асио конечно будут и мутексы, да и синхронизацию мастеробжекта (прием коллбека) надо бы сделать через strand - обёртка в асио, заставляющая все коллбеки внутри него исполняться строго неконкурентно
просто все вопросы балансировки по M потокам перекладываются на плечи фреймворка, что гуд
необходимо понимать, что все операции, связанные с помещением i-го коллбека в очередь j-го потока, не очень бесплатные, и потому оверхед стоит оценить по отношению к времени, которое требуется для каждой задачи (т.е. если они микросекундные, то в один поток последовательно получится быстрее, если они секундные и больше, то вполне имеет смысл параллелиться, конечно)
bormand 14.06.2012 11:58 # 0
Запускаем пачку рабочих тредов.
Worker thread забирает задачу из очереди (fix: и выполняет ее), затем он захватывает мутекс на мап, и вынимает из мапа все задачи, в которых зависимостью была текущая. Задачи, у которых больше нет зависимостей уходят в очередь, у которых есть - обратно в мап с ключем следующей зависимости. После этого освобождается мутекс и тред снова забирает задачу из очереди.
Как насчет такого решения?
roman-kashitsyn 14.06.2012 12:33 # 0
geust 14.06.2012 10:56 # +1
Характерно, что о многопоточности массы задумались только с появлением соотв. аппаратных возможностей на лоу-энд писюках.
http://hashcode.ru/questions/114371
roman-kashitsyn 14.06.2012 09:58 # 0
Хотя сейчас в моду больше входит модель акторов с асинхронной передачей сообщений.
bormand 14.06.2012 10:52 # 0
ctm 14.06.2012 10:24 # 0
1. стараться не юзать глобальные и статик-переменные
2. если уж так нужно, то обращения только в критических секциях
3. иные потоко-небезопасные вещи тоже.
roman-kashitsyn 14.06.2012 10:29 # +1
ctm 14.06.2012 12:23 # 0
bormand 14.06.2012 10:42 # +1
2. Защитить все что осталось критическими секциями\мутексами\рвлоками.
...
4. Профит
Но, к сожалению для скоростного приложения Роман прав. Правил нет. Только треш угар и содомия ;)
Lure Of Chaos 13.06.2012 23:25 # +3
ctm 14.06.2012 06:27 # +1
QPainterPath::MoveToElement, QPainterPath::LineToElement, QPainterPath::LineToElement, QPainterPath::LineToElement
не обязательно является rect'ом?
bormand 14.06.2012 06:50 # +2
guest 22.06.2012 11:06 # −2