我正在通过使其更加异步来改进应用程序(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类(参见this article)。
答案 0 :(得分:0)
是否有某些原因导致您无法将某种上下文对象传递给这些任务,这些任务为其提供了更新其状态的界面?因为我站在那里,听起来你对单身人士(又称全局变量)有一个非常糟糕的问题,应该通过依赖注入来解决。
如果不能选择依赖注入,那么还有另一种处理单身人士的策略。该策略基本上允许Singleton成为'堆栈'。您可以将新值“推送”到Singleton,然后访问它的每个人都会获得这个新值。然后你可以“弹出”该值,并恢复推送前的值。这不必直接用实际堆栈建模,这就是为什么我在引号中加上'push','pop'和'stack'这两个词。
你可以通过让一个线程本地Singleton用这个变量的父线程版本的值(不是整个值的堆栈,只是最高值)初始化来调整这个模型。然后,如果此线程及其子节点需要新的上下文,则可以将新值推送到线程本地Singleton。