2

I'm learning Boost.Asio, but I have a question about boost::asio::deadline_timer async_wai. Here is the code from boost home page:

//
// timer.cpp
// ~~~~~~~~~
//
// Copyright (c) 2003-2013 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//

#include <iostream>
#include <boost/asio.hpp>
#include <boost/bind.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>

class printer
{
public:
  printer(boost::asio::io_service& io)
    : timer_(io, boost::posix_time::seconds(1)),
      count_(0)
  {
    timer_.async_wait(boost::bind(&printer::print, this));
  }

  ~printer()
  {
    std::cout << "Final count is " << count_ << "\n";
  }

  void print()
  {
    if (count_ < 5)
    {
      std::cout << count_ << "\n";
      ++count_;

      timer_.expires_at(timer_.expires_at() + boost::posix_time::seconds(1));
      timer_.async_wait(boost::bind(&printer::print, this));
    }
  }

private:
  boost::asio::deadline_timer timer_;
  int count_;
};

int main()
{
  boost::asio::io_service io;
  printer p(io);
  io.run();

  return 0;
}

async_wait require the function signature like this:

void handler(
  const boost::system::error_code& error // Result of operation.
);

but in this dome, it is timer_.async_wait(boost::bind(&printer::print, this));, the signature is void print(printer*),How it works?
please help me, thank you.

hahaya
  • 106
  • 1
  • 6
  • I'd use `std::bind` and try to use as few `boost` stuff as possible (I use `boost.asio` in a project of mine and only include `boost/asio.hpp`). See http://stackoverflow.com/a/17414563/2176127 to see how to use `std::bind` instead of `boost::bind`. –  Nov 29 '13 at 08:37
  • 2
    [See this article](http://blog.think-async.com/2010/04/bind-illustrated.html) to better understand how `bind works. – Igor R. Nov 29 '13 at 14:35
  • @IgorR. Great article! –  Nov 29 '13 at 21:34

2 Answers2

4

Text from timer3 example "In this example, the boost::asio::placeholders::error argument to boost::bind() is a named placeholder for the error object passed to the handler. When initiating the asynchronous operation, and if using boost::bind(), you must specify only the arguments that match the handler's parameter list. In tutorial Timer.4 you will see that this placeholder may be elided if the parameter is not needed by the callback handler. "

You can not use boost::asio::placeholders::error or use it in timer4 example.

Example 3 without boost::asio::placeholders::error

#include <iostream>
#include <boost/asio.hpp>
#include <boost/bind.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>

void print( boost::asio::deadline_timer* t, int* count)
{
    if (*count < 5)
    {
        std::cout << *count << "\n";
        ++(*count);

        t->expires_at(t->expires_at() + boost::posix_time::seconds(1));
        t->async_wait(boost::bind(print, t, count));
    }
}

int main()
{
    boost::asio::io_service io;

    int count = 0;
    boost::asio::deadline_timer t(io, boost::posix_time::seconds(1));
    t.async_wait(boost::bind(print, &t, &count));

    io.run();

    std::cout << "Final count is " << count << "\n";

    return 0;
}

Example 4 with boost::asio::placeholders::error

#include <iostream>
#include <boost/asio.hpp>
#include <boost/bind.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>

class printer
{
    public:
        printer(boost::asio::io_service& io)
            : timer_(io, boost::posix_time::seconds(1)),
            count_(0)
    {
        timer_.async_wait(boost::bind(&printer::print, this, boost::asio::placeholders::error));
    }

        ~printer()
        {
            std::cout << "Final count is " << count_ << "\n";
        }

        void print(const boost::system::error_code &e)
        {
            if (count_ < 5)
            {
                std::cout << count_ << "\n";
                ++count_;

                timer_.expires_at(timer_.expires_at() + boost::posix_time::seconds(1));
                timer_.async_wait(boost::bind(&printer::print, this, boost::asio::placeholders::error ));
            }
        }

    private:
        boost::asio::deadline_timer timer_;
        int count_;
};

int main()
{
    boost::asio::io_service io;
    printer p(io);
    io.run();

    return 0;
}
AlexBG
  • 386
  • 1
  • 7
0

Boost.Bind silently ignores extra arguments, take a look at bind documentaion.

EDIT :

A similar question to yours was already asked, take a look at it, there is more detailed answer.

Community
  • 1
  • 1
westwood
  • 1,774
  • 15
  • 29