backoff.cc 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475
  1. /*
  2. *
  3. * Copyright 2016 gRPC authors.
  4. *
  5. * Licensed under the Apache License, Version 2.0 (the "License");
  6. * you may not use this file except in compliance with the License.
  7. * You may obtain a copy of the License at
  8. *
  9. * http://www.apache.org/licenses/LICENSE-2.0
  10. *
  11. * Unless required by applicable law or agreed to in writing, software
  12. * distributed under the License is distributed on an "AS IS" BASIS,
  13. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. * See the License for the specific language governing permissions and
  15. * limitations under the License.
  16. *
  17. */
  18. #include "src/core/lib/backoff/backoff.h"
  19. #include <algorithm>
  20. #include "src/core/lib/gpr/useful.h"
  21. namespace grpc_core {
  22. namespace {
  23. /* Generate a random number between 0 and 1. We roll our own RNG because seeding
  24. * rand() modifies a global variable we have no control over. */
  25. double generate_uniform_random_number(uint32_t* rng_state) {
  26. constexpr uint32_t two_raise_31 = uint32_t(1) << 31;
  27. *rng_state = (1103515245 * *rng_state + 12345) % two_raise_31;
  28. return *rng_state / static_cast<double>(two_raise_31);
  29. }
  30. double generate_uniform_random_number_between(uint32_t* rng_state, double a,
  31. double b) {
  32. if (a == b) return a;
  33. if (a > b) GPR_SWAP(double, a, b); // make sure a < b
  34. const double range = b - a;
  35. return a + generate_uniform_random_number(rng_state) * range;
  36. }
  37. } // namespace
  38. BackOff::BackOff(const Options& options)
  39. : options_(options),
  40. rng_state_(static_cast<uint32_t>(gpr_now(GPR_CLOCK_REALTIME).tv_nsec)) {
  41. Reset();
  42. }
  43. grpc_millis BackOff::NextAttemptTime() {
  44. if (initial_) {
  45. initial_ = false;
  46. return current_backoff_ + grpc_core::ExecCtx::Get()->Now();
  47. }
  48. current_backoff_ =
  49. (grpc_millis)(std::min(current_backoff_ * options_.multiplier(),
  50. (double)options_.max_backoff()));
  51. const double jitter = generate_uniform_random_number_between(
  52. &rng_state_, -options_.jitter() * current_backoff_,
  53. options_.jitter() * current_backoff_);
  54. const grpc_millis next_timeout = (grpc_millis)(current_backoff_ + jitter);
  55. return next_timeout + grpc_core::ExecCtx::Get()->Now();
  56. }
  57. void BackOff::Reset() {
  58. current_backoff_ = options_.initial_backoff();
  59. initial_ = true;
  60. }
  61. void BackOff::SetRandomSeed(uint32_t seed) { rng_state_ = seed; }
  62. } // namespace grpc_core