Note that there are some explanatory texts on larger screens.

plurals
  1. POOBSE and Boost.Asio: Threaded async UDP server with deadline_timer on the same io_service
    primarykey
    data
    text
    <ul> <li><strong>Platform</strong>: Windows 7 Professional 64 bit</li> <li><strong>Compiler</strong>: VS2010 Express</li> <li><strong>Boost</strong>: Version 1.49</li> <li><strong>Plugin System</strong>: OBSE 20 (for the Oblivion game by Bethesda)</li> </ul> <p>I have a class based upon the async udp examples. I run the io service itself as a thread. Here is the code for the class:</p> <pre><code> // udp buffer queues extern concurrent_queue&lt;udp_packet&gt; udp_input_queue; // input from external processes extern concurrent_queue&lt;udp_packet&gt; udp_output_queue; // output to external processes using boost::asio::ip::udp; class udp_server { public: udp_server(boost::asio::io_service&amp; io_service, short port) : io_service_(io_service), socket_(io_service_, udp::endpoint(boost::asio::ip::address_v4::from_string(current_address), port))//, // udp::v4() { // start udp receive socket_.async_receive_from( boost::asio::buffer(recv_buf), sender_endpoint_, boost::bind(&amp;udp_server::handle_receive_from, this, boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred)); send_timer_ = NULL; } ~udp_server(){ io_service_.stop(); if(send_timer_){ send_timer_-&gt;cancel(); delete send_timer_; } } void start(){ // start send timer send_timer_ = new boost::asio::deadline_timer(io_service_, boost::posix_time::milliseconds(500)); send_timer_restart(); } void handle_send_to(const boost::system::error_code&amp; error, size_t bytes_recvd); void handle_receive_from(const boost::system::error_code&amp; error, size_t bytes_recvd); //void handle_send_timer(const boost::system::error_code&amp; error); void handle_send_timer(); void send_timer_restart(); void stop() { io_service_.stop(); } private: boost::asio::io_service&amp; io_service_; udp::socket socket_; udp::endpoint sender_endpoint_; std::vector&lt;udp::endpoint&gt; clientList; //std::auto_ptr&lt;boost::asio::io_service::work&gt; busy_work; udp_buffer recv_buf; boost::asio::deadline_timer* send_timer_; }; </code></pre> <p>Now I instantiate the class and thread like this:</p> <pre><code> udp_server *udp_server_ptr=NULL; boost::asio::deadline_timer* dlineTimer=NULL; static void PluginInit_PostLoadCallback() { _MESSAGE("NetworkPipe: PluginInit_PostLoadCallback called"); if(!g_Interface-&gt;isEditor) { _MESSAGE("NetworkPipe: Starting UDP"); udp_server_ptr = new udp_server(io_service, current_port); //dlineTimer = new boost::asio::deadline_timer(io_service); udp_thread = new boost::thread(boost::bind(&amp;boost::asio::io_service::run, &amp;io_service)); // _MESSAGE("NetworkPipe: UDP Started"); NetworkPipeEnable = true; } else { _MESSAGE("NetworkPipe: Running in editor, not starting UDP"); } } </code></pre> <p>Now notice that dlineTimer is commented out above. If I enable that it ceases to function. The only way I can get the dlineTimer to function with this io service is to create it during the <code>udp_server::handle_receive_from</code> call. I think this is because it is running inside the other thread. So for some reason the <code>deadline_timer</code> object does not like being created outside the thread it needs to run inside.</p> <p>Now, in order to communicate to the main thread I use <code>concurrent_queue</code> objects. So these allow me to send messages in and out of the thread pretty simply. I could theoretically run the <code>dlineTimer</code> inside its own thread and use the output queue to manage its activity. However, I like the simplicity of having is in the same thread as the <code>udp_server</code>. For instance the <code>udp_server</code> object keeps track of clients in a vector. When the <code>deadline_timer</code> expires I cycle through the known clients and send them messages. Then I restart the timer. This makes my response independent of the udp packets that are sent to the server. So when packets arrive they are put on a queue for another part of the process. Then later data is placed on the output queue and the <code>deadline_timer</code> processes those responses and sends them to the appropriate clients.</p> <p>So my main question is: </p> <p>How do I more cleanly create the <code>deadline_timer</code> object using the same thread and same <code>io_service</code> as the <code>udp_server</code> object?</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload