LINUX.ORG.RU

C++ 11 runloop без блокировки текущего потока

 ,


0

2

Задача стоит такая чтобы обрабатывать события без блокировки текущего потока. Этот код должен оставаться в рамках потока в котором он вызывается. Код выглядит как-то так:

while (true)
{
    std::unique_lock<std::mutex> locker(_mutex);
    _mCondition.wait(locker, [&](){ return !_dequeObjects.empty(); });
    std::cout << "Received object()" << std::endl;
        
    locker.unlock();
}

Хотелось бы услышать советы лоровцев по тому как это можно сделать. Заранее спасибо.


И где тут блокировка текущего(добавляющего в deque?) потока? Ты опиши, что сделать хочешь? Очередь сообщений с обработкой в разных потоках? Тогда смотри в сторону сигналов поверх event loop

CatsCantFly
()
Ответ на: комментарий от CatsCantFly

Блокировка происходит тогда когда мы доходим до цикла, операторы после цикла не выполняться никогда если мы из него не выйдем.

ECLIPSE
() автор топика

Этот код должен оставаться в рамках потока в котором он вызывается.

А зачем, если не секрет?

Если это так необходимо, то заведи корутину (например, boost::coroutine) и в конце каждой итерации цикла возвращай управление. Соответственно, в остальном коде тебе придётся придумать, как регулярно отдавать управление обработке событий.

Ivan_qrt ★★★★★
()
Ответ на: комментарий от Ivan_qrt

А без буста никак не получится? Это очень удобная техника которая используется в gcd на objective c. Я хочу иметь такую же штуку на плюсах. Я могу дергать любой метод и не ждать пока он выполниться. Меня просто если честно убивает как реализована многопоточность на плюсах потому что очень типичная задача а реализовать быстро ее не получается.

ECLIPSE
() автор топика
Ответ на: комментарий от ECLIPSE

Вы выразите словами то, что вам хочется иметь? У вас в event_loop возникают события, обработку которых вы хотите делегировать на другие потоки?

eao197 ★★★★★
()
Ответ на: комментарий от eao197

Я хочу вызывать метод асинхронно в рамках текущего потока без блокировка потока выполнения программы.

ECLIPSE
() автор топика
Ответ на: комментарий от ECLIPSE

Я хочу вызывать метод асинхронно в рамках текущего потока без блокировка потока выполнения программы.

Другими словами, вы хотите, чтобы метод, который вы вызвали в потоке t1 выполнялся бы реально в потоке t2, а поток t1 продолжил бы свое выполнение. Так?

Результат этого метода вам как хочется получить?

В зависимости от ответов на эти вопросы найдется подходяший механизм, начиная от примитивного std::async из стандартной библиотеки, заканчивая самописными очередями сообщений и использованием готовых сторонних либ.

eao197 ★★★★★
()
Ответ на: комментарий от ECLIPSE

А зачем тебе что-то после цикла? Ну сделай условие его завершения, что бы он не вешал весь поток до принудительного убийства.

CatsCantFly
()
Ответ на: комментарий от eao197

1. Нет методы всегда выполняются в потоке t1 в котором находится очередь и цикл, а вот добавляться они могут в разных потоках.
2. Результат не нужен никогда в рамках данной задачи

Я тут нашел одну статью и сейчас читаю ее. Возможно она поможет решить задачу. https://habrahabr.ru/post/186200/

ECLIPSE
() автор топика
Ответ на: комментарий от ECLIPSE

Тогда еще одна попытка угадать то, что вам нужно:

  • у вас на потоке t1 крутится какой-то event-loop (какой, кстати?);
  • если вы в event-loop обнаруживаете какое-то IO-событие, то вы обрабатываете его;
  • так же на поток t1 другие потоки могут отправлять какие-то «методы»;
  • если поток t1 обнаруживает такой метод, он должен его вызвать, после чего он должен вернуться к event-loop-у.

Т.е. t1 у вас крутит event-loop, в котором обрабатывает как IO-события, как и «методы», отправленные на t1 из других потоков.

Так?

Или у вас на t1 event-loop-а с IO-событиями вообще нет?

eao197 ★★★★★
()
Ответ на: комментарий от eao197

Все правильно, что касается эвентов я использую вот такой вот луп

_mCondition.wait(locker, [&](){ return !_dequeObjects.empty(); });
и когда приходит notify wait перестает ждать и я обрабатываю обьект и вызываю метод который в нем.

ECLIPSE
() автор топика
Последнее исправление: ECLIPSE (всего исправлений: 1)
Ответ на: комментарий от ECLIPSE

Тогда вам прямой путь в Asio (хоть из Boost-а, хоть в standalone версию). Таски из других нитей будете пулить на нить Asio через asio::post и всего делов.

eao197 ★★★★★
()
Ответ на: комментарий от eao197

Посмотрю обязательно. Это даже лучше чем с бустом.

ECLIPSE
() автор топика
locker.unlock(); // ненужно

Если таки взять lock free реализацию очереди (в стандартной либе нетуть), и процессить её во вложенном цикле до пустоты, то можно получить очень быструю отработку пика и сон в нормальных условиях.

Но прежде стоит задаться вопросом - оно тебе надо?

pon4ik ★★★★★
()
Ответ на: комментарий от eao197

Результат этого метода вам как хочется получить?

как await в C#

anonymous
()

Убрать условную переменную (мьютекс оставить) и чекать очередь в текущем потоке по таймауту. В оставшееся время - делать полезную работу потока.

illy
()
Последнее исправление: illy (всего исправлений: 2)
Ответ на: комментарий от ECLIPSE

Если у тебя уже есть евент луп, который может в io, то асио тебе не надо. Просто кинь в него IO событие свое (если у тебя епол то eventfd тебе в руки) и по нему выгребай там свои метода с объектами и что-то там. асио имеет смысл если у тебя должно под офф и он топик собираться. Да и с сетью или файлами работать.

anonymous
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.