| // Copyright 2018 The Fuchsia Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "src/lib/backoff/exponential_backoff.h" |
| |
| #include <lib/syslog/cpp/macros.h> |
| #include <stdlib.h> |
| #include <zircon/syscalls.h> |
| |
| namespace backoff { |
| |
| ExponentialBackoff::ExponentialBackoff(fit::function<uint64_t()> seed_generator) |
| : ExponentialBackoff(zx::msec(100), 2u, zx::sec(60 * 60), std::move(seed_generator)) {} |
| |
| ExponentialBackoff::ExponentialBackoff(zx::duration initial_delay, uint32_t retry_factor, |
| zx::duration max_delay, |
| fit::function<uint64_t()> seed_generator) |
| : initial_delay_(initial_delay), |
| retry_factor_(retry_factor), |
| max_delay_(max_delay), |
| max_delay_divided_by_factor_(max_delay_ / retry_factor_), |
| rng_(seed_generator()) { |
| FX_DCHECK(zx::duration() <= initial_delay_ && initial_delay_ <= max_delay_); |
| FX_DCHECK(0 < retry_factor_); |
| FX_DCHECK(zx::duration() <= max_delay_); |
| } |
| |
| ExponentialBackoff::~ExponentialBackoff() {} |
| |
| uint64_t ExponentialBackoff::DefaultSeedGenerator() { |
| uint64_t seed = 0; |
| zx_cprng_draw(&seed, sizeof(seed)); |
| return seed; |
| } |
| |
| zx::duration ExponentialBackoff::GetNext() { |
| // Add a random component in [0, next_delay). |
| std::uniform_int_distribution<zx_duration_t> distribution(0u, next_delay_.get()); |
| zx::duration r(distribution(rng_)); |
| zx::duration result = max_delay_ - r >= next_delay_ ? next_delay_ + r : max_delay_; |
| |
| // Calculate the next delay. |
| next_delay_ = |
| next_delay_ <= max_delay_divided_by_factor_ ? next_delay_ * retry_factor_ : max_delay_; |
| return result; |
| } |
| |
| void ExponentialBackoff::Reset() { next_delay_ = initial_delay_; } |
| |
| } // namespace backoff |