【问题标题】:Boost bind AIX xlc io_service runBoost 绑定 AIX xlc io_service 运行
【发布时间】:2013-02-06 15:15:30
【问题描述】:

我正在尝试使用 boost 编译项目,将 asio::io_service 绑定到 boost::thread,并且我遇到了我不知道如何解决的错误 使用:IBM XL C/C++ for AIX,V11.1 (5724-X13),版本: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>"

导致错误的代码:

    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()));
    }

定义:

    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_;

顺便提一下,这可能只是一些标志选项,但我在任何地方都找不到 因为相同的代码在 Linux(GCC)、HP-UX(aCC) 和 Windows(MSVC) 上编译得非常好。

谢谢帮助

【问题讨论】:

    标签: boost-asio aix boost-bind xlc


    【解决方案1】:

    快速的 google 搜索表明 AIX 在重载解决方面存在问题,尤其是在涉及模板时。因此,可能值得尝试不同的方法来减少需要发生的重载解决方案的数量。

    例如,boost::mem_fn() 可以用来代替boost::bind()

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

    此外,如果编译器仍然无法解决重载问题,请考虑编写一个简单的仿函数。 boost::thread() 构造函数的唯一要求是 func 参数是可复制的,并且 func() 必须是有效的表达式。

    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)));
    

    其他需要考虑的点:

    • 宁愿编译符合标准的代码,而不是使用编译器标志来允许不符合标准的代码编译。在这种特殊情况下,io_service::run() 是一个非常量成员函数,但绑定到它的accept_io_service 实例参数作为常量引用通过boost::cref() 传递。需要添加编译器标志,例如 gcc 的 -fpermissive,以允许编译不合格代码。使用这些选项时要非常小心,因为它们可能会掩盖严重的问题。
    • 考虑将boost::shared_ptr 作为实例句柄传递给绑定调用。只要线程仍在运行,这将使io_service 保持活动状态。否则,io_service 可能会在线程仍在处理其事件循环时被删除,从而导致调用未定义行为的可能性很高。

    【讨论】:

    • 非常感谢service runner 包装,它就像一个魅力。使用boost::mem_fn() 的第一种方法没有解决The qualifier "accept_io_service_" is not defined in the current scope. 的原因,这很奇怪,因为它是一个成员变量。评论其他点,boost::cref() 只是我在论坛某处找到的测试,在其他平台上我按照我的预期使用boost::shared_ptr。再次感谢您的好建议。
    • 还有一个问题,在 AIX 6.1 (xlC_r V9.0) 上无法编译,使用 service_runner 时出现 /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 (). 错误。您能否使用mem_fn 更好地解释我首次提出的解决方案?因为我不太了解std::size_t (io_service::*run)() = &amp;io_service::run; 声明。谢谢
    • @Pinker:我必须查看用法才能确定问题,因为我不熟悉 AIX。该语句将run 声明为指向io_service 成员函数的指针,该函数返回std::size_t 并且不接受任何参数。然后它将io_service::run() 的地址分配给成员函数指针。目标是明确的,防止编译器在重载的io_service::run() 上推断bind 调用中的签名。
    • 正如您建议的acceptor_thread_.reset(new boost::thread(service_runner(accept_io_service_)));service_runner 是您在答案中发布的内容的精确副本。但我得到了第一个解决方案^^。再次非常感谢您的帮助。
    • @Pinker:使用 gcc 和 clang,我无法使用提供的代码复制错误。对于 Boost 1.49,当表达式 func() 对提供的 func 参数无效时,第 62 行将出错。 service_runner 提供了一个operator(),所以它应该是有效的。我只能通过将提供的类型更改为boost::thread 来复制错误,例如提供boost::shared_ptr&lt;service_runner&gt; 而不是service_runner
    【解决方案2】:

    只是好奇,您是否正在为您正在使用的编译器使用 IBM boost 库补丁? http://www-01.ibm.com/support/docview.wss?uid=swg27006911

    【讨论】:

    • 不,自 3 年前使用 boost 1.40.0(即 13 个版本)以来,我预计这些变通方法中的大多数已经在 boost 库中,并且还预计会修复很多错误这 13 个版本(即使我使用 boost 1.49.0)
    • 平克,恕我直言,你太乐观了。我更喜欢自己运行 boost 回归测试来检查每个版本。
    【解决方案3】:

    查看尝试的 4 个可能候选人的消息,差异似乎与 const 相关

    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 *)".
    

    由于您使用的是 V11.1 编译器,因此有几个默认未启用的修复程序,您可以尝试使用以下选项

    -qxflag=EnableIssue214PartialOrdering 这将启用与 C++ 核心语言问题 214 相关的几个修复

    -qxflag=FunctionCVTmplArgDeduction2011 这使得一些 C++2011 对参数推导的澄清

    这些更改在 V12.1 编译器上是默认的,但在 V11.1 编译器上没有

    【讨论】:

      【解决方案4】:

      如果有人偶然发现这个问题,我会添加额外的响应。 因为我发现这与编译器无法解析使用哪个函数有关,如果函数名称相同,但参数不同。

      例子:

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

      将无法正常工作,并会导致与上述类似的错误。
      但是像这样更改名称:

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

      ...会很好地工作。

      这绝对是比创建包装器更少的开销解决方案(正如我自己在观察到这一点之前所做的那样)。

      希望有人会觉得这很有用。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2015-12-28
        • 2016-01-07
        • 1970-01-01
        • 2013-03-11
        • 1970-01-01
        • 2011-07-26
        • 2010-10-27
        • 2018-11-26
        相关资源
        最近更新 更多