- Platform: Windows 7 Professional 64 bit
- Compiler: VS2010 Express
- Boost: Version 1.49
- Plugin System: OBSE 20 (for the Oblivion game by Bethesda)
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:
    // udp buffer queues
    extern concurrent_queue<udp_packet> udp_input_queue; // input from external processes
    extern concurrent_queue<udp_packet> udp_output_queue; // output to external processes
    using boost::asio::ip::udp;
    class udp_server
    {
    public:
        udp_server(boost::asio::io_service& 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(&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_->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& error, size_t bytes_recvd);
        void handle_receive_from(const boost::system::error_code& error, size_t bytes_recvd);
        //void handle_send_timer(const boost::system::error_code& error);
        void handle_send_timer();
        void send_timer_restart();
        void stop()
        {
            io_service_.stop();
        }
        private:
            boost::asio::io_service& io_service_;
            udp::socket socket_;
            udp::endpoint sender_endpoint_; 
            std::vector<udp::endpoint> clientList;
            //std::auto_ptr<boost::asio::io_service::work> busy_work;
            udp_buffer recv_buf;
            boost::asio::deadline_timer* send_timer_;
    };
Now I instantiate the class and thread like this:
    udp_server *udp_server_ptr=NULL;
    boost::asio::deadline_timer* dlineTimer=NULL;
    static void PluginInit_PostLoadCallback()
    {   
        _MESSAGE("NetworkPipe: PluginInit_PostLoadCallback called");
        if(!g_Interface->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(&boost::asio::io_service::run, &io_service));         
            //
            _MESSAGE("NetworkPipe: UDP Started");
            NetworkPipeEnable = true;
        }
        else
        {
            _MESSAGE("NetworkPipe: Running in editor, not starting UDP");
        }    
    }
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 udp_server::handle_receive_from call.  I think this is because it is running inside the other thread.  So for some reason the deadline_timer object does not like being created outside the thread it needs to run inside.
Now, in order to communicate to the main thread I use concurrent_queue objects.  So these allow me to send messages in and out of the thread pretty simply.  I could theoretically run the dlineTimer 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 udp_server.  For instance the udp_server object keeps track of clients in a vector.  When the deadline_timer 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 deadline_timer processes those responses and sends them to the appropriate clients.
So my main question is:
How do I more cleanly create the deadline_timer object using the same thread and same io_service as the udp_server object?
