2

I am implementing some asio operations using boost, I've encountered an interface problem, whom which I am not receiving 'handlers' in initialization, but right after,

This forces me to write a 'busy' loop, what I'd like to do is have the io_service run even without having at least 1 handler, is it possible? what is the way to handle this? do a wait on handlers on the service? this is my code..

    /** : */
    void                Run             () { while(true) {m_srv.run(); Sleep(1);} } // once 1 handler is inside service, thread will not be in busy loop
private: // members:

    io_service  m_srv;

Any suggestions? thanks

This is the code problem: (m_drv is a task that operates boost::thread(io_service::run..))

class App : public Base::Application
{
public:
    /** : */
    App(char* name, char* id) : Application(name, id), m_drv("NetTask"), m_worker("Worker"), m_acceptor(m_worker, Drv(), &OnAccept, 4567)
    {
        m_acceptor.Accept(Drv());
    }

    /** : */
    inline DriverImp& Drv() { return static_cast<DriverImp&>(m_drv.Imp());}

    /** : */
    inline Reactor& Worker() { return m_worker; }
public: 
    APTR(Socket) m_sock;
private: // members:
    Driver      m_drv;
    Reactor     m_worker;
    Acceptor    m_acceptor;
};
Alon
  • 1,776
  • 13
  • 31
  • You have a slight problem with your loop: The documentation for [`run`](http://www.boost.org/doc/libs/1_55_0/doc/html/boost_asio/reference/io_service/run/overload1.html) states that if `run` returns you have to call [`reset`](http://www.boost.org/doc/libs/1_55_0/doc/html/boost_asio/reference/io_service/reset.html) before calling `run` again. – Some programmer dude Nov 21 '13 at 09:25
  • I don't want to ever leave run :), handlers are supposed to exist after start.. but ok, I will look it up, still what is the way to avoid the busy loop? – Alon Nov 21 '13 at 09:25
  • It was a couple of years ago since I last used Boost ASIO, and I don't have my source available right now, but as I remember I just put the `io_service.run()` call in its own thread, and didn't have a loop. I *think* it was done before any async calls were made, and it worked fine anyway. – Some programmer dude Nov 21 '13 at 09:28
  • not according to the boost documentation.. they say you must call run after at least 1 handler is inside the service – Alon Nov 21 '13 at 09:35
  • Also, since the run will exit after it's out of work, I don't need to call reset..? – Alon Nov 21 '13 at 09:36
  • I don't think that it's possible for `io_service.run()` to block without at least one handler running. However you could simply add a handler for a timer with an extremely long duration to ensure that run does not return... – kenba Nov 21 '13 at 12:36

1 Answers1

5

You need to use io_service::work:

boost::asio::io_service        service;
boost::asio::io_service::work  work( service );

Note: in destructor the work object notifies the service that the work is complete and io_service::run() may return.

Ivan
  • 2,007
  • 11
  • 15
  • I don't see how it helps, worker says it will finish when there are no more handlers, I don't want it to ever finish – Alon Nov 21 '13 at 09:55
  • @Alon, sorry, didn't get you. Is the problem solved? – Ivan Nov 21 '13 at 09:59
  • nope, the worker still exits since it has no work, so I would still have to do while(true) – Alon Nov 21 '13 at 10:01
  • It means you're using io_service::work incorrectly. Show us the code. – Ivan Nov 21 '13 at 10:02
  • In general I am creating the service and then appending work to it, and not vice versa...what is the way to make the service keep checking for work without doing a busy loop? – Alon Nov 21 '13 at 10:43
  • Again, it doesn't work that means you're doing it incorrectly. Show me the code or I'll not be able to help. And _forget_ about that loop. – Ivan Nov 21 '13 at 11:38
  • Ive posted it. what piece are you missing? – Alon Nov 21 '13 at 12:11
  • 3
    I do not see you use `io_service::work` anywhere in your code. But it is exactly what you need. As long as the `work` object remains alive, any subsequent calls to `io_service.run()` will not return. So you create the `io_service`, then create the `work(io_service)` and then you can call `io_service.run()` whenever you want and be sure that it does not return until you destroy the `work` object (and then finishes all ahndlers). – DeVadder Nov 21 '13 at 12:36
  • thanks DeVadder, @IvanGrynko, thanks for the answer, please revise a 3rd line to call io_service.run() for future users :) – Alon Nov 21 '13 at 13:12