Интеграция Boost.Asio в GUI - PullRequest
       15

Интеграция Boost.Asio в GUI

0 голосов
/ 14 апреля 2020

У меня есть простой код, использующий boost.asio, например следующий:

namespace net = boost::asio;
int main()
{
    net::io_context ioContext;
    AsyncClass myClass(ioContext);

    myClass.onAsyncEvent1([] { /* do stuff */ })
    myClass.onAsyncEvent2([] { /* do stuff */ });

    ioContext.run();
    return 0;
}

Я хочу добавить этот код в приложение GUI (Android / Linux / Windows) .

Решения, которые я нашел в сети, очень неэффективны для меня. Наиболее распространенными являются:

  1. с таймером GUI и вызовом оттуда функции poll_one.
  2. Использование опроса:
    1. Проверьте, получено ли сообщение от GUI и обработайте его, если будет
    2. вызов poll_one
    3. сумма сна

Но эти два решения просто сохраняют Высокая загрузка ЦП для того, чтобы ничего не делать, а на мобильном телефоне это просто означает бесполезную трату масла.

ЧТО Я ХОЧУ

Я хотел бы заблокировать все, пока что-то не произойдет, и справиться все события asyn c в основном потоке GUI

namespace net = boost::asio;
int main()
{
    net::io_context ioContext;
    AsyncClass myClass(ioContext);

    // gui code
    myClass.onAsyncEvent1([] { /* update gui */ });
    myClass.onAsyncEvent2([] { /* update gui */ });

    thread asyncThread{[&ioContext] {
        ioContext.wait();
        // this is blocking until the message is done
        sendMessageToGUI(GUI_CUSTOM_EVENT);
    }

    while(true)
    {
        GUIEvent event;
        // this is blocking
        GetMessage(event);

        if (event == GUI_CUSTOM_EVENT)
            ioContext.run_one();  // run_one or poll_one are the same here
    }
    return 0;
}

К сожалению, Boost.Asio не предоставляет такой утилиты ...

ВОПРОСЫ

  1. Почему такая функция не реализована в Boost? Или, может быть, Boost.Asio просто не подходит для асин c кода в GUI приложениях
  2. Это неправильный метод? Может быть, умнее способ сделать это.

ВОЗМОЖНОЕ РЕШЕНИЕ?

Возможное решение может просто вызвать sendMessageToGUI из обратного вызова ...

namespace net = boost::asio;
int main()
{
 net::io_context ioContext, guiContext;
 AsyncClass myClass(ioContext);

 // non gui code
 myClass.onAsyncEvent1([] { /* do stuff */ });
 myClass.onAsyncEvent2([] { /* do stuff */ });
 myClass.onAsyncEvent3([] { /* do stuff */ });
 myClass.onAsyncEvent4([] { /* do stuff */ });

 // gui code
 myClass.onAsyncEvent1([&guiContext]
 {
   postGUIMessage(GUI_CUSTOM_MESSAGE);
   guiContext.post([]{
     // this will unlock the main thread
     ui->laber->setText("yes!");
   }
 });

 myClass.onAsyncEvent4([&guiContext]
 {
   postGUIMessage(GUI_CUSTOM_MESSAGE);
   guiContext.post([]{
     // this will unlock the main thread
     ui->laber->setText("yes!");
   }
 });

 thread_pool.enqueue{[&ioContext] { ioContext.run(); }

 while(true)
 {
   GUIEvent event;
   // this is blocking
   GetMessage(event);

   if (event == GUI_CUSTOM_EVENT)    
     guiContext.poll();  

   return 0;
}

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

...