为并发运行时实现任务局部变量

Ste*_*erg 6 c++ concurrency-runtime concrt

我正在通过使其更加异步来改进应用程序(Win64,C++).我正在使用并发运行时,到目前为止它对我来说非常有用.

该应用程序基本上执行了许多转换数据的"作业".为了跟踪每个作业的作用,某些子系统配有代码来跟踪作业执行的某些操作.以前,这将使用表示当前正在执行的作业的单个全局变量,以便能够注册跟踪信息,而无需在调用链中一直传递上下文信息.每个作业也可以使用ConcRT来并行化作业本身.一切都很好.

现在,我正在重构应用程序,以便我们可以并行执行顶级作业.每个作业都作为ConcRT任务执行,这适用于除需要跟踪的作业之外的所有作业.

我基本上需要的是一种将一些上下文信息与任务相关联的方法,并将该流程交给该任务产生的任何其他任务.基本上,我需要"任务本地"变量.

使用ConcRT,我们不能简单地使用线程本地来存储上下文信息,因为作业可能使用ConcRT生成其他作业,并且这些作业将在任意数量的线程上执行.

我当前的方法涉及在启动时创建许多Scheduler实例,并在专用于该作业的调度程序中生成每个作业.然后我可以使用该Concurrency::CurrentScheduler::Id()函数来检索整数ID,我可以将其用作关键来计算上下文.这可以工作,但单步进入Concurrency::CurrentScheduler::Id()程序集使我有点畏缩,因为它执行多个虚函数调用和安全检查,这增加了相当多的开销,这是一个问题,因为这个查找需要在极高的情况下完成在某些情况下.

那么 - 有没有更好的方法来实现这一目标?我本来希望有一个一流的TaskLocal/userdata机制,它允许我将单个上下文指针与当前的Scheduler/SchedulerGroup/Task相关联,我可以用很少的开销检索它.

每当ConcRT线程抓取新任务时调用的钩子将是我的理想选择,因为我可以检索Scheduler/ScheduleGroup ID并将其存储在本地线程中以获得最小的访问开销.唉,我看不到任何方式来注册这样的钩子,似乎不可能为PPL /代理实现自定义的Scheduler类(参见这篇文章).

Omn*_*ous 0

是否有某种原因导致您无法将某种上下文对象传递给这些任务,为它们提供更新状态的接口?因为从我的立场来看,听起来单例(又名全局变量)有一个非常严重的问题,这个问题应该通过依赖注入来解决。

如果依赖注入不可行,还有另一种处理单例的策略。该策略基本上是允许单例成为一个“堆栈”。您可以将新值“推送”到单例,然后访问它的每个人都会获得这个新值。然后您可以将值“弹出”并恢复推送前的值。这不必直接使用实际堆栈进行建模,这就是为什么我将“push”、“pop”和“stack”放在引号中。

您可以通过使用该变量的父线程版本的值(不是整个堆栈值,只是顶部值)初始化线程本地单例来调整此模型以适应您的情况。然后,如果该线程及其子线程需要新的上下文,您可以将新值推送到线程本地单例中。