所以
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);
一个未充分记录的限制是如何从签名中推导出错误传播。
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 的完成令牌机制之外进行访问。