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

  • SEARCH
  • Home
  • 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 9027029
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: June 16, 20262026-06-16T06:39:41+00:00 2026-06-16T06:39:41+00:00

I find myself writing code that basically looks like this: using boost::system::error_code; socket.async_connect(endpoint, [&](error_code

  • 0

I find myself writing code that basically looks like this:

using boost::system::error_code;

socket.async_connect(endpoint, [&](error_code Error)
{
  if (Error)
  {
    print_error(Error);
    return;
  }

  // Read header
  socket.async_read(socket, somebuffer, [&](error_code Error, std::size_t N)
  {
    if (Error)
    {
      print_error(Error);
      return;
    }

    // Read actual data
    socket.async_read(socket, somebuffer, [&](error_code Error, std::size_t N)
    {
      // Same here...
    });
  });
};

So basically I’m nesting callbacks in callbacks in callbacks, while the logic is simple and “linear”.

Is there a more elegant way of writing this, so that the code is both local and in-order?

  • 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-16T06:39:42+00:00Added an answer on June 16, 2026 at 6:39 am

    One elegant solution is to use coroutines. Boost.Asio supports both stackless coroutines, which introduce a small set of pseudo-keywords, and stackful coroutines, which use Boost.Coroutine.


    Stackless Coroutines

    Stackless coroutines introduce a set of pseudo-keywords preprocessor macros, that implement a switch statement using a technique similar to Duff’s Device. The documentation covers each of the keywords in detail.

    The original problem (connect->read header->read body) might look something like the following when implemented with stackless coroutines:

    struct session
     : boost::asio::coroutine
    {
      boost::asio::ip::tcp::socket socket_;
      std::vector<char> buffer_;
      // ...
    
      void operator()(boost::system::error_code ec = boost::system::error_code(),
                      std::size_t length = 0)  
      {
        // In this example we keep the error handling code in one place by
        // hoisting it outside the coroutine. An alternative approach would be to
        // check the value of ec after each yield for an asynchronous operation.
        if (ec)
        {
          print_error(ec);
          return;
        }
    
        // On reentering a coroutine, control jumps to the location of the last
        // yield or fork. The argument to the "reenter" pseudo-keyword can be a
        // pointer or reference to an object of type coroutine.
        reenter (this)
        {
          // Asynchronously connect. When control resumes at the following line,
          // the error and length parameters reflect the result of
          // the asynchronous operation.
          yield socket_.async_connect(endpoint_, *this);
    
          // Loop until an error or shutdown occurs.
          while (!shutdown_)
          {
            // Read header data. When control resumes at the following line,
            // the error and length parameters reflect the result of
            // the asynchronous operation.
            buffer_.resize(fixed_header_size);
            yield socket_.async_read(boost::asio::buffer(buffer_), *this);
    
            // Received data.  Extract the size of the body from the header.
            std::size_t body_size = parse_header(buffer_, length);
    
            // If there is no body size, then leave coroutine, as an invalid
            // header was received.
            if (!body_size) return;
    
            // Read body data. When control resumes at the following line,
            // the error and length parameters reflect the result of
            // the asynchronous operation.
            buffer_.resize(body_size);
            yield socket_.async_read(boost::asio::buffer(buffer_), *this);
    
            // Invoke the user callback to handle the body.
            body_handler_(buffer_, length);
          }
    
          // Initiate graceful connection closure.
          socket_.shutdown(tcp::socket::shutdown_both, ec);
        } // end reenter
      }
    }
    

    Stackful Coroutines

    Stackful coroutines are created using the spawn() function. The original problem may look something like the following when implemented with stackful coroutines:

    boost::asio::spawn(io_service, [&](boost::asio::yield_context yield)
      {
        boost::system::error_code ec;
        boost::asio::ip::tcp::socket socket(io_service);
    
        // Asynchronously connect and suspend the coroutine.  The coroutine will
        // be resumed automatically when the operation completes.
        socket.async_connect(endpoint, yield[ec]);
        if (ec)
        {
          print_error(ec);
          return;
        }
    
        // Loop until an error or shutdown occurs.
        std::vector<char> buffer;
        while (!shutdown)
        {
          // Read header data.
          buffer.resize(fixed_header_size);
          std::size_t bytes_transferred = socket.async_read(
            boost::asio::buffer(buffer), yield[ec]);
    
          if (ec)
          {
            print_error(ec);
            return;
          }
    
          // Extract the size of the body from the header.
          std::size_t body_size = parse_header(buffer, bytes_transferred);
    
          // If there is no body size, then leave coroutine, as an invalid header
          // was received.
          if (!body_size) return;
    
          // Read body data.
          buffer.resize(body_size);
          bytes_transferred =
            socket.async_read(boost::asio::buffer(buffer), yield[ec]);
    
          if (ec)
          {
            print_error(ec);
            return;
          }
    
          // Invoke the user callback to handle the body.
          body_handler_(buffer, length);
        }
    
        // Initiate graceful connection closure.
        socket.shutdown(tcp::socket::shutdown_both, ec);
       });
    
    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

I find myself writing code that looks something like this: $(document).ready(function(){ updateStuff(); $('select').change(function(){ updateStuff();
I find myself writing code that looks like this a lot: set<int> affected_items; while
I find myself writing a lot of code in my views that looks like
Using ValueInjecter, I often find myself writing code like this: var foo1 = new
When using PHP, I find myself writing code like this a lot: $target =
Often I find myself writing code like this: if (Session != null) { Session.KillAllProcesses();
In PHP I find myself writing code like this frequently: $a = isset($the->very->long->variable[$index]) ?
Quite often I find myself writing code like this: Dim oRenewalOrder = (From c
So I find myself writing this code all the time: [TestMethod] [Description(Asserts that an
I find myself frequently writing code like this: k = 0 for i in

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.