Нужна помощь по асинхронной неблокирующей загрузке файлов с boost::asio и boost::iostreams (или чем-то другим?)

Я пишу на C++ и пытаюсь загрузить файл изображения асинхронно. После некоторых исследований я обнаружил некоторые упоминания об использовании boost:: asio и boost:: iostreams для этого. Тем не менее, документация и пример для boost:: asio в основном связаны с сокетами, поэтому мне это мало помогает.

Вот что мне нужно:

  • Загрузите файл асинхронно и по завершении загрузки выполнит функцию обратного вызова (в моем случае функция обратного вызова выполняет объект функции javascript с использованием механизма v8 javascript)
  • Функция обратного вызова должна выполняться в том же потоке, что и основная функция.(Потому что v8 не является потокобезопасным.)
  • Нужно работать на Linux и Windows. (отдельные реализации в порядке)

Итак, что-то вроде этого было бы действительно хорошо:

async_read("test.jpg", &the_callback_function);

Функция не должна блокироваться, и после завершения загрузки файла она должна запустить 'the_callback_function'.

Редактировать: как указал joshperry, boost:: asio не сможет отправить обратно в главный поток. Так что, думаю, мне не нужно ограничиваться только boost:: asio и boost: iostreams. Любая библиотека c/ C++, которая может помочь с этим требованием, должна подойти. Спасибо!

1 ответ

Решение

Вы можете делать то, что вы хотите, с небольшим количеством строительных лесов, но для того, чтобы обратный вызов был выполнен в вашем основном потоке, основной поток должен ожидать чего-то, что сигнализирует о готовности обратного вызова. Вот один из способов сделать это. Я предполагаю, что ваш основной поток уже имеет некоторую форму цикла выполнения.

  • Добавьте потокобезопасную очередь уведомлений, которую фоновые потоки могут использовать для уведомления основного потока об обратных вызовах, которые должны быть выполнены.
  • Измените ваш основной цикл выполнения так, чтобы он ожидал в этой очереди вместе с любыми другими источниками событий, которые он ожидает (очевидно, я предполагаю, что у вас есть управляемый событиями цикл в вашем основном потоке, измените его на вкус, если вы этого не сделаете:).
  • Продолжайте использовать asio async_read с обратным вызовом, только обратный вызов не будет напрямую выполнять функцию завершения, вместо этого он поставит ее в очередь для выполнения.

Нетрудно построить такую ​​очередь с использованием STL и объектов синхронизации (например, предоставляемых Boost.Thread). Построить его для масштабирования с высокой пропускной способностью без конфликтов - это другой вопрос, но не похоже, что вам нужно такое масштабирование. Даже если другие библиотеки сделают все это за вас, создание чего-то подобного самостоятельно станет отличным упражнением для всех, кто занимается многопоточным программированием, особенно если один или несколько задействованных компонентов не являются реентерабельными.

Другие вопросы по тегам