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
()
Вы не можете добавлять комментарии в эту тему: топик перемещен в архив.