Название: Не блокирующий обмен данными между потоками Отправлено: JamS007 от Июль 28, 2010, 22:56 Приветствую, господа.
Задача: Есть сервер. При инициализации создаю пул служебных потоков. (-1 от количества ядер на машине или 1, если ядро одно). В основном потоке подключаються клиенты и читаються запросы от них. Также в основном потоке декодируються запросы от клинтов, и в зависимости от запроса "напрягаеться" служебный поток. Служебные потоки должны выполнять потенциально медленные задачи (чтение/запись с HDD, всевозможные проверки, и т.д.) Хочу сделать максимально продуктивный сервер, в рамках Qt (другое не предлагать), поэтому, стараюсь комбинировать асинхронность с многопоточностью. Если есть идеи - с удовольствием выслушаю. Цель: Среди задач выполняемых служебными потоками, есть такие, которые требуют подтверждения успешного выполнения. И тут возникает проблема: Каким способом можна вызвать на обработку функцию из служебного потока, так, чтоб поток, ее вызывающий (в данном случае основной поток), не останавливался (ведь в нем крутяться и другие клиенты, и остановка недопустима), и после выполнения функции в основной поток, передавалось потверждение выполнения. Также интересует каким способом можна организовать очередь обработок в одном потоке, например: в поток поступают несколько запросов на выполнение разных функций, как их распределить в очередь? Заранеее спасибо, даже за внимание :) Название: Re: Не блокирующий обмен данными между потоками Отправлено: BlackTass от Июль 29, 2010, 00:46 Ну не блокировать основной поток можно посредством проброса сигнала из рабочего в основной по завершении. Главное только таски между собой различить по какому-нить ид.
Про очередь не понял вопроса. В том порядке в каком приходят в том и ставьте, ну или если есть приоритеты у тасков, то тасуйте слегка очередь/делайте несколько очередей (как в консульствах). Название: Re: Не блокирующий обмен данными между потоками Отправлено: JamS007 от Июль 29, 2010, 10:59 Про сигналы я уже думал. Они действительно не блокируют основной поток поток, но на сигналы не приходит ответ, тоесть сигнал выслан, и все, как он там дальше будет обрабатыватся уже не известно.
Можно конечно сделать такуй связку сигналов: Основной поток --- (запрос) ---> дочерний поток Дочерний поток --- (ответ) ---> основной поток но это как-то геморно, та и в таком случае невозможно узнать точно, подтверждение на какую команду было выслано, ведь дочерний поток может задержаться с ответом, а потом прислать два ответа одновременно, и какой из них принадлежит какому запросу? Тут, конечно, тоже можно выкрутиться, например прысилать какой-нибудь идентификатор запроса, но у меня команды записываються в ByteArray, и он весит порядка 40кб. (Знаю, много) И таскать каждый раз эту команду в поток и назад не хочеться. Есть идеи? Название: Re: Не блокирующий обмен данными между потоками Отправлено: BlackTass от Июль 29, 2010, 11:13 Я про это и имел в виду когда писал про ид. Основной поток присылает вместе с запросом его уникальный ид (который сам генерит банальным инкрементом). Дочерний поток присылает ответ вместе с этим идшником и основной поток уже смотрит что вообще за команда то была по ид.
Название: Re: Не блокирующий обмен данными между потоками Отправлено: SABROG от Июль 29, 2010, 12:24 Стандартный метод (http://thesmithfam.org/blog/2009/09/30/lock-free-multi-threading-in-qt/) вызвать слот из другого потока, который вышлет сигнал, когда данные или работа будет завершена. Тут только возникает проблема с контекстом локальных переменных, если их значения нужно восстановить после получения результата и продолжить некую логику зависящую от них и возвращенного значения (как это сделано в closure'ах).
Название: Re: Не блокирующий обмен данными между потоками Отправлено: JamS007 от Июль 29, 2010, 16:47 SABROG, спасибо, познавательная статейка. В принципе так и думал делать :)
Еще один вопрос: есть 2 потока. Пусть в первом из них будет динамически создана переменная, тоесть память возметься из кучи, а в самом потоке будет только указатель на нее. Сможет ли второй поток обратиться по переданному указателю к этой переменной, если поток 1 находиться в ожидании и не работает. Я имею ввиду, кокой из потоков в конце концов обработает обращение к памяти, тот что запрашивает переменную из памяти, или тот, что ее создал? По другому можно сформульровать вопрос так: динамические переменные создаються адресном пространстве потока, или в общем? И если в общем, то можно ли к ним получить доступ из разных потоков? Название: Re: Не блокирующий обмен данными между потоками Отправлено: SABROG от Июль 29, 2010, 16:55 В принципе через локальный QEventLoop можно симулировать сохранение локальных переменных и ожидание результатов из слота.
Название: Re: Не блокирующий обмен данными между потоками Отправлено: BRE от Июль 29, 2010, 16:56 По другому можно сформульровать вопрос так: динамические переменные создаються адресном пространстве потока, или в общем? И если в общем, то можно ли к ним получить доступ из разных потоков? Все потоки работают в одном адресном пространстве.Название: Re: Не блокирующий обмен данными между потоками Отправлено: Igors от Август 02, 2010, 13:43 По другому можно сформульровать вопрос так: динамические переменные создаються адресном пространстве потока, или в общем? И если в общем, то можно ли к ним получить доступ из разных потоков? В общем, если "только чтение" то проблем никакихНазвание: Re: Не блокирующий обмен данными между потоками Отправлено: Barmaglodd от Август 02, 2010, 14:17 В общем, если "только чтение" то проблем никаких Угу, у вас все операции с памятью как транзакции в БД работают? Особенно интересно в контексте конструктора сложного объекта.Название: Re: Не блокирующий обмен данными между потоками Отправлено: Igors от Август 02, 2010, 14:42 Угу, у вас все операции с памятью как транзакции в БД работают? Особенно интересно в контексте конструктора сложного объекта. До чого тут транзакцii БД? :) Не понял Вашего вопроса, поясните на примере Название: Re: Не блокирующий обмен данными между потоками Отправлено: Barmaglodd от Август 02, 2010, 15:08 Я к тому, что переключение контекста может быть и в середине конструктора, но если создать объект, потом передать указатель и не трогать объект, то да проблем никаких. :)
|