Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • Home
  • SEARCH
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 8732279
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: June 13, 20262026-06-13T09:24:41+00:00 2026-06-13T09:24:41+00:00

Boris’ article shows us how to create extension of boost::asio. I try to add

  • 0

Boris’ article shows us how to create extension of boost::asio. I try to add signal_set and async_wait on registered signals. Then the program hangs until a second SIGINT is triggered. Though, I would like to finish it properly within one signal only.

Here is my code. I test it with gcc-4.6.3 and boost-1.52.0 on Ubuntu.

To compile –

gcc -I/boost_inc -L/boot_lib main.cpp -lpthread -lboost_system -lboost_thread

#include <boost/asio.hpp> 
#include <iostream> 
#include <boost/thread.hpp> 
#include <boost/bind.hpp> 
#include <boost/scoped_ptr.hpp> 
#include <boost/shared_ptr.hpp> 
#include <boost/weak_ptr.hpp> 
#include <cstddef> 

template <typename Service> 
class basic_timer 
  : public boost::asio::basic_io_object<Service> 
{ 
  public: 
    explicit basic_timer(boost::asio::io_service &io_service) 
      : boost::asio::basic_io_object<Service>(io_service) 
    {} 

    void wait(std::size_t seconds) 
    { return this->service.wait(this->implementation, seconds); } 

    template <typename Handler> 
    void async_wait(std::size_t seconds, Handler handler) 
    { this->service.async_wait(this->implementation, seconds, handler); } 
}; 

class timer_impl;

template <typename TimerImplementation = timer_impl> 
class basic_timer_service 
  : public boost::asio::io_service::service 
{ 
  public: 
    static boost::asio::io_service::id id; 

    explicit basic_timer_service(boost::asio::io_service &io_service) 
      : boost::asio::io_service::service(io_service), 
      async_work_(new boost::asio::io_service::work(async_io_service_)), 
      async_thread_(
        boost::bind(&boost::asio::io_service::run, &async_io_service_)) 
    {} 

    ~basic_timer_service() 
    { 
      async_work_.reset(); 
      async_io_service_.stop(); 
      async_thread_.join();  // program is blocked here until the second 
                             // signal is triggerd
      async_io_service_.reset();
    } 

    typedef boost::shared_ptr<TimerImplementation> implementation_type; 

    void construct(implementation_type &impl) 
    { 
      impl.reset(new TimerImplementation()); 
    } 

    void destroy(implementation_type &impl) 
    { 
      impl->destroy(); 
      impl.reset(); 
    } 

    void wait(implementation_type &impl, std::size_t seconds) 
    { 
      boost::system::error_code ec; 
      impl->wait(seconds, ec); 
      boost::asio::detail::throw_error(ec); 
    } 

    template <typename Handler> 
    class wait_operation 
    { 
      public: 
        wait_operation(
          implementation_type &impl,
          boost::asio::io_service &io_service, 
          std::size_t seconds, Handler handler) 
          : impl_(impl), 
          io_service_(io_service), 
          work_(io_service), 
          seconds_(seconds), 
          handler_(handler) 
        {} 

        void operator()() const 
        { 
          implementation_type impl = impl_.lock(); 
          if (!io_service_.stopped() && impl) 
          { 
              boost::system::error_code ec; 
              impl->wait(seconds_, ec); 
              this->io_service_.post(
                boost::asio::detail::bind_handler(handler_, ec)); 
          } 
          else 
          { 
              this->io_service_.post(
                boost::asio::detail::bind_handler(
                  handler_, boost::asio::error::operation_aborted)); 
          } 
      } 

      private: 
        boost::weak_ptr<TimerImplementation> impl_; 
        boost::asio::io_service &io_service_; 
        boost::asio::io_service::work work_; 
        std::size_t seconds_; 
        Handler handler_; 
    }; 

    template <typename Handler> 
    void async_wait(
      implementation_type &impl, 
      std::size_t seconds, Handler handler) 
    { 
      this->async_io_service_.post(
        wait_operation<Handler>(
          impl, this->get_io_service(), seconds, handler)); 
    } 

  private: 
    void shutdown_service() 
    {} 

    boost::asio::io_service async_io_service_; 
    boost::scoped_ptr<boost::asio::io_service::work> async_work_; 
    boost::thread async_thread_; 
}; 

class timer_impl 
{ 
  public: 
    timer_impl() 
    {} 

    ~timer_impl() 
    {} 

    void destroy() 
    {} 

    void wait(std::size_t seconds, boost::system::error_code &ec) 
    { 
      sleep(seconds);
      ec = boost::system::error_code(); 
    } 
};


typedef basic_timer<basic_timer_service<> > timer; 

template <typename TimerImplementation> 
boost::asio::io_service::id basic_timer_service<TimerImplementation>::id; 
void wait_handler(const boost::system::error_code &ec) 
{ 
  std::cout << "5 s." << std::endl; 
} 

int main() 
{ 
  {
    boost::asio::io_service io_service; 
    boost::asio::signal_set signals(io_service);
    timer t(io_service);

    signals.add(SIGINT);
    signals.async_wait(
      boost::bind(&boost::asio::io_service::stop, &io_service));

    t.async_wait(2, wait_handler); 

    std:: cout << "async called\n" ;
    io_service.run(); 
  } 

  { // this block will not be executed
    boost::asio::io_service io_service; 
    timer t(io_service); 

    t.async_wait(2, wait_handler); 
    std:: cout << "async called\n" ;
    io_service.run(); 
  }
  return 0;
} 
  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-06-13T09:24:42+00:00Added an answer on June 13, 2026 at 9:24 am

    After tried an example offered by the author of asio, I confronted the same behavior. Consequently, I dig into the library source and found that the source use io_service_impl‘s interfaces rather than ones of io_service. Furthermore, an operation functor posted to the io_service_impl is different from ones invoked by the io_service. Altogether, I decided to rewrite the timer example according to the internal interfaces of asio.

    I hereby present the rewritten timer example.

    #include <boost/asio.hpp> 
    #include <iostream> 
    #include <boost/thread.hpp> 
    #include <boost/bind.hpp> 
    #include <boost/scoped_ptr.hpp> 
    #include <boost/shared_ptr.hpp> 
    #include <boost/weak_ptr.hpp> 
    #include <cstddef> 
    
    #define get_service_impl(X) \
      ba::use_service<bad::io_service_impl>(X)
    
    namespace ba = boost::asio;
    namespace bad = boost::asio::detail;
    
    // Nothing changed
    template <typename Service> 
    class basic_timer 
      : public boost::asio::basic_io_object<Service> 
    { 
    public: 
      explicit basic_timer(boost::asio::io_service &io_service) 
        : boost::asio::basic_io_object<Service>(io_service) 
      {} 
    
      void wait(std::size_t seconds) 
      { return this->service.wait(this->implementation, seconds); } 
    
      template <typename Handler> 
      void async_wait(std::size_t seconds, Handler handler) 
      { this->service.async_wait(this->implementation, seconds, handler); } 
    }; 
    
    // Nothing changed
    class timer_impl 
    { 
    public: 
      void wait(std::size_t seconds, boost::system::error_code &ec) 
      { 
        sleep(seconds);
        ec = boost::system::error_code(); 
      } 
    };
    
    // ----- Change a lot! --------
    class basic_timer_service 
    : public boost::asio::io_service::service 
    { 
    public:
      typedef boost::asio::detail::socket_ops::shared_cancel_token_type 
        implementation_type;
    
      static boost::asio::io_service::id id; 
    
      explicit basic_timer_service(boost::asio::io_service &io_service) 
        : boost::asio::io_service::service(io_service), 
          io_service_impl_(get_service_impl(io_service)),
          work_io_service_( new boost::asio::io_service ),
          work_io_service_impl_(get_service_impl(*work_io_service_)),
          work_(new ba::io_service::work(*work_io_service_)),
          work_thread_() // do not create thread here
      {} 
    
      ~basic_timer_service() 
      {  shutdown_service(); } 
    
      void construct(implementation_type &impl) 
      { impl.reset(new timer_impl()); } 
    
      void cancel(implementation_type &impl)
      {
            impl.reset((void*)0, boost::asio::detail::socket_ops::noop_deleter());
      }
    
      void destroy(implementation_type &impl) 
      { impl.reset(); } 
    
      void shutdown_service() 
      {
        work_.reset();
        if(work_io_service_.get()){
          work_io_service_->stop();
          if (work_thread_.get()){
            work_thread_->join();
            work_thread_.reset();
          }
        }
        work_io_service_.reset();
      } 
    
      void wait(implementation_type &impl, std::size_t seconds) 
      { 
        boost::system::error_code ec; 
        // XXX I not sure this is safe
        timer_impl *impl_ptr = static_cast<timer_impl*>(impl.get());
        impl_ptr->wait(seconds, ec); 
        boost::asio::detail::throw_error(ec); 
      } 
    
      template <typename Handler> 
      class wait_operation
      : public boost::asio::detail::operation
      { 
      public: 
        BOOST_ASIO_DEFINE_HANDLER_PTR(wait_operation);
    
        // namespace ba = boost::asio
        // namespace bad = boost::asio::detail
        wait_operation(
          bad::socket_ops::weak_cancel_token_type cancel_token,
          std::size_t seconds, 
          bad::io_service_impl& ios,
          Handler handler) 
          : bad::operation(&wait_operation::do_complete), 
          cancel_token_(cancel_token),
          seconds_(seconds),
          io_service_impl_(ios),
          handler_(handler) 
        {} 
    
        static void do_complete(
          bad::io_service_impl *owner,
          bad::operation *base,
          boost::system::error_code const & /* ec */ ,
          std::size_t /* byte_transferred */ )
        { 
          wait_operation *o(static_cast<wait_operation*>(base));
          ptr p = { boost::addressof(o->handler_), o, o};
    
          // Distinguish between main io_service and private io_service
          if(owner && owner != &o->io_service_impl_)
          { // private io_service
    
            // Start blocking call
            bad::socket_ops::shared_cancel_token_type lock =
              o->cancel_token_.lock();
    
            if(!lock){
              o->ec_ = boost::system::error_code(
                ba::error::operation_aborted,
                                boost::system::system_category());
            }else{
              timer_impl *impl = static_cast<timer_impl*>(lock.get());
              impl->wait(o->seconds_, o->ec_);
            }
            // End of blocking call
    
            o->io_service_impl_.post_deferred_completion(o);
            p.v = p.p = 0;
          }else{ // main io_service
            bad::binder1<Handler, boost::system::error_code> 
              handler(o->handler_, o->ec_);
            p.h = boost::addressof(handler.handler_);
            p.reset();
            if(owner){
              bad::fenced_block b(bad::fenced_block::half);
              boost_asio_handler_invoke_helpers::invoke(
                            handler, handler.handler_);
            }
          } 
        } 
    
      private: 
        bad::socket_ops::weak_cancel_token_type cancel_token_; 
        std::size_t seconds_; 
        bad::io_service_impl &io_service_impl_; 
        Handler handler_; 
        boost::system::error_code ec_;
      }; 
    
      template <typename Handler> 
      void async_wait(
        implementation_type &impl, 
        std::size_t seconds, Handler handler) 
      { 
        typedef wait_operation<Handler> op;
        typename op::ptr p = {
          boost::addressof(handler),
          boost_asio_handler_alloc_helpers::allocate(
            sizeof(op), handler), 0};
        p.p = new (p.v) op(impl, seconds, io_service_impl_, handler);
        start_op(p.p);
        p.v = p.p = 0;
      }
    
    protected:
      // Functor for runing background thread
      class work_io_service_runner
      {
      public:  
        work_io_service_runner(ba::io_service &io_service)
          : io_service_(io_service) {}
    
        void operator()(){ io_service_.run(); }
      private:
        ba::io_service &io_service_;
      };
    
      void start_op(bad::operation* op)
      {
        start_work_thread();
        io_service_impl_.work_started();
        work_io_service_impl_.post_immediate_completion(op);
      }
    
      void start_work_thread()
      {
        bad::mutex::scoped_lock lock(mutex_);
        if (!work_thread_.get())
        {
          work_thread_.reset(new bad::thread(
              work_io_service_runner(*work_io_service_)));
        }
      }
    
      bad::io_service_impl& io_service_impl_;
    
    private: 
      bad::mutex mutex_;
      boost::scoped_ptr<ba::io_service> work_io_service_;
      bad::io_service_impl &work_io_service_impl_;
      boost::scoped_ptr<ba::io_service::work> work_;
      boost::scoped_ptr<bad::thread> work_thread_;
    }; 
    
    boost::asio::io_service::id basic_timer_service::id; 
    
    typedef basic_timer<basic_timer_service> timer; 
    
    void wait_handler(const boost::system::error_code &ec) 
    { 
      if(!ec)
        std::cout << "wait_handler is called\n" ;
      else
        std::cerr << "Error: " << ec.message() << "\n";
    } 
    
    int main() 
    { 
      {
        boost::asio::io_service io_service; 
        boost::asio::signal_set signals(io_service);
        timer t(io_service); 
    
        signals.add(SIGINT);
        signals.async_wait(
          boost::bind(&boost::asio::io_service::stop, &io_service));
    
        t.async_wait(2, wait_handler); 
    
        std:: cout << "async called\n" ;
        io_service.run(); 
        std:: cout << "exit loop\n";
      } 
    
      {
        boost::asio::io_service io_service; 
        timer t(io_service); 
    
        t.async_wait(2, wait_handler); 
        std:: cout << "async called\n" ;
        io_service.run(); 
      }
      return 0;
    } 
    

    To compile

    gcc -I/boost_inc -L/boot_lib main.cpp -lpthread -lboost_system -lboost_thread

    The new timer works fine. Still I would like to know how to write a non-intrusive extension of asio.

    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

If you try to add style declarations in the head of a document, IE
* * * * * /bin/bash -l -c 'cd /Users/boris/projects/MyApp/ && rails runner Resque.enqueue(Place)'
I want to inject some HTML into some websites with a Chrome extension, and
I want to create an XML file from java 6 (it's the first time
I'm using jsRender and I wanted to display my data as columns rather then
Reading through an Article about custom Objects: http://technet.microsoft.com/en-us/library/ff730946.aspx I wonder why i get a
Is it possible to add zoom to mobile targeted website? I use webview and
I've just seen this really nice talk Rock Hard: C++ Evolving by Boris Jabes.
var metin = baris; var icerikoku = Hello Baris. What is surname Baris. Bye
Suppose I have this : item_one = Object.find(1) rescue item_one, value = [Object.first, true]

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.