我查看了Blink代码库以回答有关JavaScript中可能的最大计时器数量的question信息。

新计时器由DOMTimerCoordinator::InstallNewTimeout()创建。它调用NextID()检索可用的整数键。然后,它将新计时器和相应的键插入timers_中。

int timeout_id = NextID();
timers_.insert(timeout_id, DOMTimer::Create(context, action, timeout,
                                            single_shot, timeout_id));


NextID()以从1到231-1的循环顺序获取下一个id:

int DOMTimerCoordinator::NextID() {
  while (true) {
    ++circular_sequential_id_;

    if (circular_sequential_id_ <= 0)
      circular_sequential_id_ = 1;

    if (!timers_.Contains(circular_sequential_id_))
      return circular_sequential_id_;
  }
}


如果所有ID都在使用,该怎么办?
是什么阻止NextID()进入无限循环?

我在answer中对该问题进行了更详细的说明。

最佳答案

我需要一点儿了解这一点,但我相信我明白了。

这些步骤对我来说变得有意义。


circular_sequential_id_用作唯一标识符。它没有公开,但从其他信息来看,我怀疑它是32位的int(例如std::int32_t)。
我怀疑是circular_sequential_id_(或classstruct的成员变量。因此,在每次调用DOMTimerCoordinator之后,它都会“记住”最后返回的值。输入NextID()时,NextID()首先递增:

    ++circular_sequential_id_;

增量circular_sequential_id_可能迟早会引起溢出(嗯。如果我没记错的话,这被认为是Undefined Behavior,但在现实世界中,它大多只是绕来绕去)并变为负数。为了解决这个问题,下一行适用于:

    if (circular_sequential_id_ <= 0)
      circular_sequential_id_ = 1;

循环中的最后一条语句检查生成的ID是否仍在任何计时器中使用:

    if (!timers_.Contains(circular_sequential_id_))
      return circular_sequential_id_;


如果未使用,则返回ID。否则,“ Sam,再玩一次。”


这给我带来了最合理的答案:

是的,这可能会变成无休止的循环...

...如果231-1个计时器已被占用,因此所有ID已被消耗。


我假设使用231-1计时器,您还有许多其他必不可少的问题。 (单独,想象一下那些计时器可能需要的存储以及处理所有计时器的时间...)
即使231-1计时器不是致命问题,该功能也可能会进一步循环,直到其中一个计时器释放其ID并可以再次使用它为止。因此,如果资源(计时器的免费ID)暂时不可用,++circular_sequential_id_;将被阻止。


三思而后行,2.选项是理论上的。我不敢相信有人会以此方式管理有限的资源。

我猜想,这段代码是在假设永远不会同时存在231-1个计时器的情况下工作的,因此它将通过几次迭代找到一个可用的ID。

关于c++ - 是什么阻止DOMTimerCoordinator::NextID进入无限循环?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/53127713/

10-12 15:16