如何使用带有多个签名的asio并发通道(&C++-20协程)

问题描述 投票:0回答:1

所以

concurrent_channel
docs 说:

通道支持的消息集由其模板参数指定

这意味着您可以发送不止一种消息类型。 (对吗?) concurrent_channel 引用 表示

typename... Signatures
,它看起来像您指定多个参数集的地方。

因此,从一个工作示例开始,在我看来,您只需添加更多签名,也许像这样:

using my_channel = channel<
        void(boost::system::error_code, std::size_t), // this alone, straight from the example, works.
        void(std::string, float) // adding this breaks it inscrutably
        >;

我对此类事情的所有尝试都以

async_receive()
async_send()
调用站点上的大量编译器错误结束(有些引用
payload_type
这在概念上是有意义的,但我不理解或在文档中看到) .

有人有这方面的工作示例,特别是使用协程的示例吗?

(洞穴和只是通过联合/变体/任何会给我的祖先带来耻辱。我也意识到,我正在混合

channel
concurrent_channel
,但相同的解决方案应该适用于两者。)

PS: 在我摆弄通道时,似乎如果您不指定

error_code
作为第一个参数,事情就会崩溃。这是否记录在我错过的地方?正如一个示例所使用的那样,仅
void()
似乎也有效。更神秘的是,工作示例发送了一个
error_code
,但知道不接收它回来

using token_channel = channel<void(boost::system::error_code, std::size_t)>;
...
co_await tokens.async_send(
    boost::system::error_code{}, bytes_per_token,
    use_awaitable);      
   ...
// How did they know not to expect error_code back?
std::size_t bytes_available = co_await tokens.async_receive(use_awaitable);
c++ asynchronous c++20 boost-asio
1个回答
0
投票

一个未充分记录的限制是如何从签名中推导出错误传播。

use_awaitable
标记将这些转换为异常。我可能是错的,但似乎至少必须提供一个 error_code 参数才能起作用。

如果您使用回调样式,这是不是强制的,您可以通过执行简单的异步接收来检查:

chan.async_receive([](auto&&...) { std::cout << "DETECT\n" << __PRETTY_FUNCTION__ << std::endl; });

对于您的示例,将打印如下内容:Live On Coliru

DETECT
main()::<lambda(auto:53&& ...)> [with auto:53 = {boost::system::error_code, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >}]
DETECT
main()::<lambda(auto:54&& ...)> [with auto:54 = {std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, float}]

请注意,channel_message 的构造函数似乎存在 QOI 问题,比较:https://coliru.stacked-crooked.com/a/20385fd813ee6ddd。

当使用另一个对错误进行特殊处理的完成标记时,会出现类似的错误小说:

auto x = chan.async_receive(asio::use_future);

事实上,需要禁用概念支持才能使其通过编译器:

#define BOOST_ASIO_DISABLE_CONCEPTS

即便如此,

x
的推导类型是
void
,而不是预期的
future<>
实例。通常的技巧
asio::as_tuple
asio::redirect_error
没有帮助:https://coliru.stacked-crooked.com/a/8418ae75969257d2

总而言之,有足够的证据表明一些原本应该可以工作的东西被破坏了。我注意到所有示例和测试都没有行使多重签名支持。考虑使用从该问题中提取的最简单的独立示例来报告问题:https://github.com/boostorg/asio/issues

解决方法?

从概念上讲,我希望

co_await
返回一个
variant<Tuple1, Tuple2>
,其中元组类型为
tuple<error_code,string>
tuple<string, float>
。您可以通过将签名更改为

来自己模仿
void(variant<Tuple1, Tuple2>)

而是在 Asio 的完成令牌机制之外进行访问。

© www.soinside.com 2019 - 2024. All rights reserved.