返回资讯中心
外部精选
软件工程
#开发者实时流

开发者用类型系统在Pystd中改进ThreadPoolExecutor

来源标题:A slightly better ThreadPoolExecutor in Pystd through types

开发者通过引入类型系统,在Pystd中实现了比标准库略好的ThreadPoolExecutor,解决了此前无法通过future对象从任务返回值的问题。方案容忍少量面向对象设计和每个任务一次额外malloc,避免了模板化带来的代码膨胀和编译变慢。该执行器适用于长时间运行、资源消耗大的任务。

Hacker News 最新ibobev2026/11/2 · 2 天前7 分钟阅读

以下正文由 AI 翻译自 Hacker News 最新(原文版权归原站所有),可能存在偏差,重要内容请以原文为准。

在上一篇文章中,我们研究了一个简单的多线程任务执行器,它的行为大致类似于 Python 标准库中的对应实现。它最缺失的功能是能够通过 future 对象从运行的任务中返回值。在像 Python 这样完全动态的语言中,这相当直接,而在像 C++ 这样具有静态类型的语言中,事情就比较棘手了。

最简单的解决方案只是把你的 Executor 类做成模板,由你想要运行的函数进行参数化。明显的缺点是代码膨胀。如果你的程序中有 Executor<Foo> 和 Executor<Bar>,它们的全部代码都会在二进制文件中重复,即使其中 90% 可能是相同的。另外,由于模板实例化的魔力,编译速度会更慢。另一个缺点是你无法用一个 Executor 运行做不同事情、尤其是具有不同返回值类型的任务。

我开始尝试同时解决这两个问题。结果发现,如果你愿意容忍一点点面向对象和每个任务多一次 malloc,就能得到一个相当不错的解决方案。由于任务执行器用于运行时间长、消耗大量资源的事情,对于大多数用例来说,这种开销是微不足道的。而如果对某人来说这绝对、确实至关重要,他们反正会自己动手实现。无论如何,试图迎合那些用例都将是白费力气。

这些需求指向了一个相当明显的解决方案。执行器处理 TypeErasedFuture/Promise 类型,这些类型通过老派的 void 指针和虚函数存储所有任务元数据。具体的 Future 和 Promise 任务只是它们之上的类型安全垫片。整个实现只需要使用两次 reinterpret_cast,这相当令人惊讶。我本以为会更多,但我想有时候你就是会走运。

Executor 得以保持为具体类。其中唯一的模板是 submit 方法,它保留类型擦除后的任务并返回一个有类型的 future 对象。

使用它并不像 Python 对应物那样简单,但仍然相当容易。在你编写了一个实现执行器任务接口的类之后,提交工作和消费结果是这样完成的。

如果返回值不是 void,.get() 将返回结果对象的引用。最大化模板化带来的易用性与最小化代码生成之间的权衡,在你为了让它运转起来而需要编写的额外样板代码中清晰可见。但作为回报,你既减小了二进制体积,又加快了编译时间。这究竟是改进还是损害,取决于你。

这段代码不会赢得任何健壮性奖项(不过,在如今 AI 垃圾遍地的时代,谁知道呢),但最终结果对于仅一个晚上的工作来说已经足够好了。

正文由 探How 从来源站点 RSS 同步,内容未经改写;遇到排版缺失或需要图片、视频时请以原文为准。

打开原文
去社区讨论 →