在关于resumable functions的文章中,在关于限制的部分中列出了三个限制:
- 可恢复的函数不能使用可变数量的参数。对于需要varargs的情况,可以将参数展开放在一个函数中,该函数在执行参数展开后调用可恢复函数。
- 可恢复功能的返回类型必须为
future<T>
或shared_future<T>
。对T的限制由std::future
定义,而不是此提案,但T
必须是可复制或可移动的类型,或“void
”。还必须能够构造一个没有参数的T
变量;也就是说,如果它是类类型,它必须具有可访问(隐式或显式)默认构造函数。- Await表达式可能不会出现在异常处理程序的主体内,并且在执行线程持有任何类型的锁时不应执行。
这种限制背后必然有一个原因,由于我对并发性缺乏了解,我无法推断出原因是什么。有人可以为我这个话题开心吗?
这个限制是指C风格的可变参数函数还是C ++ 11可变参数函数?
va_*
宏完成的 magic trickery 有关吗?在这两种情况下,我认为编译器可以足够聪明地推断出要使用的函数。
我理解退回std::future
或std::shared_future
的原因,但我猜测可用类型背后的限制原因与期货可以使用的类型有关。
因此,本文提出用两个新的关键词(可恢复和等待)来扩展语言,提供可恢复函数的行为,但最后它信任现有的构造,以在函数和函数之间传递可恢复函数的返回值。来电者。
为什么不为返回值提出某种语言扩展?可能(可能)释放对默认的可构造和可复制/可移动类型的限制,并修复返回类型和返回类型之间的分析:
因此应该注意到函数从外部(调用者)和内部观察到的行为之间存在不对称性:外部透视图是函数在第一个暂停点返回类型
返回类型future<T>
的值,而内部透视图是函数通过return语句(...)T
的值
我认为在捕获异常时等待某些事情没有任何意义,但我对锁定线程的限制没有任何线索。
答案 0 :(得分:3)
我很确定所有这些限制都与可恢复功能的上下文必须“保存”和“恢复”这一事实有关 - 我希望该机制将创建一个临时的“堆栈副本”或相似的东西。所以:
可变数量的参数
这实际上意味着使用va_arg
功能的东西 - 不是因为所涉及的宏,而是因为外部代理无法知道实际参数的数量 - 对于printf
,你必须阅读格式字符串,对于其他一些格式字符串,最后一个标记为NULL
。那么需要节省多少背景?
锁定线程
所以我们刚才说“我们不希望这个线程被打断”,然后我们去说“现在让我们运行别的东西”。这就像是说“拜托,在我洗澡的时候,在任何情况下我都不会被打断”,同时说“你可以在2分钟内打电话给我......” - 假设洗澡时间超过2分钟,其中一个是不真实的。
默认可构造
我很确定这里的逻辑是,如果要构造的返回值必须将参数传递给构造函数,它将使整个概念变得非常复杂。你怎么会描述这样的事情?而你也必须在暂停状态下“坚持”这些论点。再次,使上下文的保存更加复杂。