我查看了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_
(或class
)struct
的成员变量。因此,在每次调用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/