Что мешает DOMTimerCoordinator :: NextID войти в бесконечный цикл?

Я заглянул в кодовую базу Blink, чтобы ответить на этот вопрос. вопрос о максимально возможном количестве таймеров в JavaScript.

Новые таймеры созданы 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:

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_;
}
}

Что произойдет, если все идентификаторы используются?
Что мешает NextID() от входа в бесконечный цикл?

Весь процесс объясняется более подробно в моем ответ на этот вопрос.

0

Решение

Мне нужно было немного понять, но я верю, что понял.

Это шаги, которые превратили это в смысл для меня.

  1. circular_sequential_id_ используется в качестве уникального идентификатора. Это не разоблачено, но из другой информации я подозреваю, что это int с 32 бит (например, std::int32_t).

  2. Я подозреваю circular_sequential_id_ является переменной-членом class (или же struct) DOMTimerCoordinator, Следовательно, после каждого звонка NextID() он «запоминает» последнее возвращенное значение. когда NextID() введен circular_sequential_id_ увеличивается первым:

        ++circular_sequential_id_;
  3. Приращение ++circular_sequential_id_; может рано или поздно вызвать переполнение (Uuuh. Если я правильно помню, это считается Неопределенное поведение но в реальном мире это в основном просто оборачивается.) и становится отрицательным. Чтобы справиться с этим, следующая строка подходит для:

        if (circular_sequential_id_ <= 0)
    circular_sequential_id_ = 1;
  4. Последний оператор в цикле проверяет, используется ли сгенерированный идентификатор в каком-либо таймере:

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

    Если не используется, идентификатор возвращается. В противном случае, «Играй снова, Сэм».

Это подводит меня к наиболее разумному ответу:

Да, это может стать бесконечной петлей …

…если 231 — 1 таймеры были заняты и, следовательно, все идентификаторы были использованы.

  1. Я предполагаю с 231 — 1 таймеры у вас гораздо более существенные другие проблемы. (В одиночку представляю себе хранилище, которое может понадобиться этим таймерам, и время для обработки всех из них …)

  2. Даже если 231 — 1 таймеры не являются фатальной проблемой, функция может продолжать работать до тех пор, пока один из таймеров не освободит свой ID, и он может быть снова занят. Так, NextID() будет блокировать, если ресурс (свободный идентификатор для таймера) временно недоступен.

Подумав дважды, вариант 2. довольно теоретический. Я не могу поверить, что кто-то будет управлять ограниченными ресурсами таким образом.

Я думаю, этот код работает в предположении, что никогда не будет 231 — 1 таймер одновременно, и, следовательно, он найдет свободный идентификатор с несколькими итерациями.

2

Другие решения

Других решений пока нет …