0

Im trying to compile project using boost, binding asio::io_service to boost::thread, and Im getting errors that I dont know how to resolve Using: IBM XL C/C++ for AIX, V11.1 (5724-X13), Version: 11.01.0000.0006 (AIX 7.1)

    "/home/clag/projects/tomas/include/boost/asio/detail/posix_fd_set_adapter.hpp", line 33.30: 1540-0198 (W) The omitted keyword "private" is assumed for base class "noncopyable".
    "/home/clag/projects/tomas/ots/src/agent/agent.cc", line 50.46: 1540-0219 (S) The call to "boost::bind" has no best match.
    "/home/clag/projects/tomas/ots/src/agent/agent.cc", line 50.58: 1540-1229 (I) Argument number 1 is an rvalue of type "overloaded function: boost::asio::io_service::run".
    "/home/clag/projects/tomas/ots/src/agent/agent.cc", line 50.100: 1540-1229 (I) Argument number 2 is an rvalue of type "const boost::reference_wrapper<const boost::asio::io_service>".
    "/home/clag/projects/tomas/include/boost/bind/bind_mf_cc.hpp", line 30.5: 1540-1202 (I) No candidate is better than "boost::bind<unsigned long,boost::asio::io_service,boost::reference_wrapper<const boost::asio::io_service> >(unsigned long (io_service::*)() const, reference_wrapper<const boost::asio::io_service>)".
    "/home/clag/projects/tomas/ots/src/agent/agent.cc", line 50.58: 1540-1231 (I) The conversion from argument number 1 to "unsigned long (boost::asio::io_service::*)() const" uses the resolved overloaded function "size_t boost::asio::io_service::run()".
    "/home/clag/projects/tomas/ots/src/agent/agent.cc", line 50.100: 1540-1231 (I) The conversion from argument number 2 to "boost::reference_wrapper<const boost::asio::io_service>" uses "the identity conversion".
    "/home/clag/projects/tomas/include/boost/bind/bind_mf_cc.hpp", line 20.5: 1540-1202 (I) No candidate is better than "boost::bind<unsigned long,boost::asio::io_service,boost::reference_wrapper<const boost::asio::io_service> >(unsigned long (io_service::*)(), reference_wrapper<const boost::asio::io_service>)".
    "/home/clag/projects/tomas/ots/src/agent/agent.cc", line 50.58: 1540-1231 (I) The conversion from argument number 1 to "unsigned long (boost::asio::io_service::*)()" uses the resolved overloaded function "size_t boost::asio::io_service::run()".
    "/home/clag/projects/tomas/ots/src/agent/agent.cc", line 50.100: 1540-1231 (I) The conversion from argument number 2 to "boost::reference_wrapper<const boost::asio::io_service>" uses "the identity conversion".
    "/home/clag/projects/tomas/ots/src/agent/agent.cc", line 52.35: 1540-0219 (S) The call to "boost::bind" has no best match.
    "/home/clag/projects/tomas/ots/src/agent/agent.cc", line 52.47: 1540-1229 (I) Argument number 1 is an rvalue of type "overloaded function: boost::asio::io_service::run".
    "/home/clag/projects/tomas/ots/src/agent/agent.cc", line 52.98: 1540-1229 (I) Argument number 2 is an rvalue of type "boost::asio::io_service *".
    "/home/clag/projects/tomas/include/boost/bind/bind_mf_cc.hpp", line 30.5: 1540-1202 (I) No candidate is better than "boost::bind<unsigned long,boost::asio::io_service,boost::asio::io_service *>(unsigned long (io_service::*)() const, io_service *)".
    "/home/clag/projects/tomas/ots/src/agent/agent.cc", line 52.47: 1540-1231 (I) The conversion from argument number 1 to "unsigned long (boost::asio::io_service::*)() const" uses the resolved overloaded function "size_t boost::asio::io_service::run()".
    "/home/clag/projects/tomas/ots/src/agent/agent.cc", line 52.98: 1540-1231 (I) The conversion from argument number 2 to "boost::asio::io_service *" uses "the identity conversion".
    "/home/clag/projects/tomas/include/boost/bind/bind_mf_cc.hpp", line 20.5: 1540-1202 (I) No candidate is better than "boost::bind<unsigned long,boost::asio::io_service,boost::asio::io_service *>(unsigned long (io_service::*)(), io_service *)".
    "/home/clag/projects/tomas/ots/src/agent/agent.cc", line 52.47: 1540-1231 (I) The conversion from argument number 1 to "unsigned long (boost::asio::io_service::*)()" uses the resolved overloaded function "size_t boost::asio::io_service::run()".
    "/home/clag/projects/tomas/ots/src/agent/agent.cc", line 52.98: 1540-1231 (I) The conversion from argument number 2 to "boost::asio::io_service *" uses "the identity conversion".
    "/home/clag/projects/tomas/include/boost/asio/impl/write.hpp", line 276.7: 1540-0198 (W) The omitted keyword "private" is assumed for base class "detail::base_from_completion_cond<CompletionCondition>".
    "/home/clag/projects/tomas/include/boost/asio/impl/write.hpp", line 276.7: 1540-0198 (W) The omitted keyword "private" is assumed for base class "detail::base_from_completion_cond>boost::asio::detail::transfer_all_t>"

Code that is causing errors:

    acceptor_thread_.reset(new boost::thread(boost::bind(&boost::asio::io_service::run, boost::cref(*accept_io_service_))));
    for (int i = 0; i < agent_config_.threads(); i++) {
        thread_group_.create_thread(boost::bind(&boost::asio::io_service::run, work_io_service_.get()));
    }

Definitions:

    boost::shared_ptr<boost::asio::io_service> accept_io_service_;
    boost::shared_ptr<boost::thread> acceptor_thread_;
    boost::shared_ptr<boost::asio::io_service> work_io_service_;
    boost::thread_group thread_group_;

Just to mention, this will probably will be just some flag option, but I cant find it anywhere Because same code compiles perfectly fine on Linux(GCC), HP-UX(aCC) and Windows(MSVC).

Thx for help

Pinker
  • 65
  • 8

4 Answers4

2

A quick google search suggest that AIX has had issues with overload resolution, especially when templates are involved. As such, it may be worth trying different approaches to reduce the amount of overload resolutions that need to occur.

For example, boost::mem_fn() could be used in place of boost::bind().

std::size_t (io_service::*run)() = &io_service::run;
boost::thread t(boost::mem_fn(run), io_service);

Furthermore, if the compiler is still having issues resolving the overloads, then consider writing a simple functor. The only requirement for the boost::thread() constructor is that the func argument is copyable and func() must be a valid expression.

struct service_runner
{
  explicit service_runner(boost::shared_ptr<boost::asio::io_service> io_service)
    : io_service(io_service)
  {}
  std::size_t operator()() { return io_service->run(); }
  boost::shared_ptr<boost::asio::io_service> io_service;
};

...

boost::thread t((service_runner(io_service)));

Other points to take into consideration:

  • Prefer compiling conforming code, rather than using compiler flags to allow nonconforming code to compile. In this particular case, io_service::run() is a non-const member function, but the accept_io_service instance argument being bound to it is passed as a constant reference through boost::cref(). Compiler flags, such as gcc's -fpermissive, need to be added to allow for the nonconforming code to compile. Be very careful in using these options, as they may mask serious problems.
  • Consider passing boost::shared_ptr as the instance handle to the binding calls. This will keep the io_service alive as long as the thread is still running. Otherwise, the io_service could be deleted while a thread is still processing its event loop, resulting in a high chance of invoking undefined behavior.
Tanner Sansbury
  • 51,153
  • 9
  • 112
  • 169
  • Thank you so much for the `service runner` wrap, it worked like a charm. First method using `boost::mem_fn()` didnt work out cause of `The qualifier "accept_io_service_" is not defined in the current scope.`, which is weird cause its a member variable. To comment on other points, `boost::cref()` was just a test that I found somewhere on forums, on other platforms I am using `boost::shared_ptr` as Im supposed to. Thank you again for great suggestion. – Pinker Feb 22 '13 at 12:22
  • One more question, on AIX 6.1 (xlC_r V9.0) it does not compile, Im getting `/include/boost/thread/detail/thread.hpp", line 62.17: 1540-0204 (S) An expression of type "boost::thread *" must not be followed by the function call operator ().` error when using `service_runner`. Can you maybe explain me better first proposed solution using `mem_fn`? Since I dont realy understand `std::size_t (io_service::*run)() = &io_service::run;` statement. Thank you – Pinker Mar 04 '13 at 07:40
  • @Pinker: I'd have to see the usage to be able to determine the issue, as I am not familiar with AIX. The statement declares `run` as a pointer to an `io_service` member function on that returns `std::size_t` and accepts no arguments. It then assigns the address of `io_service::run()` to the member-function pointer. The goal was to be explicit, preventing the compiler from having to deduce the signature in the `bind` call on the overloaded [`io_service::run()`](http://www.boost.org/doc/libs/1_53_0/doc/html/boost_asio/reference/io_service/run.html). – Tanner Sansbury Mar 05 '13 at 13:49
  • Just as you suggested `acceptor_thread_.reset(new boost::thread(service_runner(accept_io_service_)));`, `service_runner` is exact copy of what you have posted in your answer. But I got the first solution working ^^. Thank you very much again for your help. – Pinker Mar 06 '13 at 08:16
  • @Pinker: With gcc and clang, I was not able to duplicate the error with the provided code. For Boost 1.49, line 62 will error when the expression `func()` is invalid for the provided `func` argument. `service_runner` provides an `operator()`, so it should be valid. I was only able to duplicate the error by changing the type being provided to `boost::thread`, such as providing `boost::shared_ptr` instead of `service_runner`. – Tanner Sansbury Mar 06 '13 at 17:51
1

Just curious, are you using the IBM boost library patch for the compiler you are using? http://www-01.ibm.com/support/docview.wss?uid=swg27006911

  • Nope, since its date 3 years back, using boost 1.40.0 (which is 13 releases back), I expected majority of those workarounds already be in boost libraries, and also expected alot of bugs fixed in those 13 releases (even though Im using boost 1.49.0) – Pinker Feb 26 '13 at 08:07
  • Pinker, IMHO you are too optimistic. I prefer to check each version myself running boost regression tests. – vond Mar 10 '13 at 18:46
0

Looking at the messages for the 4 possible candidates attempted, the differences seem to be const related

No candidate is better than "boost::bind<unsigned long,boost::asio::io_service,boost::reference_wrapper<const boost::asio::io_service> >(unsigned long (io_service::*)() const, reference_wrapper<const boost::asio::io_service
>)".
No candidate is better than "boost::bind<unsigned long,boost::asio::io_service,boost::reference_wrapper<const boost::asio::io_service> >(unsigned long (io_service::*)(), reference_wrapper<const boost::asio::io_service>)".
No candidate is better than "boost::bind<unsigned long,boost::asio::io_service,boost::asio::io_service *>(unsigned long (io_service::*)() const, io_service *)".
No candidate is better than "boost::bind<unsigned long,boost::asio::io_service,boost::asio::io_service *>(unsigned long (io_service::*)(), io_service *)".

Since you are using the V11.1 compiler, there are a couple of fixes not enabled by default that you could try using the following options

-qxflag=EnableIssue214PartialOrdering This will enable several fixes related to C++ core language issue 214

-qxflag=FunctionCVTmplArgDeduction2011 This enables some C++2011 clarifications to argument deduction

These changes are the default on the V12.1 compiler, but not on the V11.1 compiler

Pinker
  • 65
  • 8
0

I'm adding additinal response, if someone stumbles upon this problem in general. Because I have found out that this is related to compiler not being able to resolve which function to use, if functions have the same name, but different parameters.

Example:

void test(int a);
void test(int a, int b);

Will not work, and will cause similar error as above.
But changing the name like this:

void test(int a);
void test2(int a, int b);

...will work perfectly fine.

This is definitely less overhead solution than creating wrappers (as I myself was doing till observing this).

Hope that someone will find this useful.

Pinker
  • 65
  • 8