blob: f0d87ded3067f0f52a784cf18b06ce31c2547695 [file] [log] [blame] [edit]
// Copyright 2024 The ChromiumOS Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef SHILL_NETWORK_TRIAL_SCHEDULER_H_
#define SHILL_NETWORK_TRIAL_SCHEDULER_H_
#include <base/functional/callback_forward.h>
#include <base/memory/weak_ptr.h>
#include <base/time/time.h>
#include "shill/event_dispatcher.h"
namespace shill {
// This class performs the exponential backoff scheduling strategy:
// - The 1st trial is triggered immediately when ScheduleTrial() is called.
// - The interval between 1st and 2nd trials being triggered is greater or equal
// to kBaseInterval.
// - The interval between the following trials being triggered grows
// exponentially (i.e. the interval will be doubled each time) until saturated
// to kMaxInterval.
class TrialScheduler {
public:
// Base time interval between two trials. Should be doubled at every new
// trial.
static constexpr base::TimeDelta kBaseInterval = base::Seconds(3);
// Min time delay between two trials.
static constexpr base::TimeDelta kMinDelay = base::Seconds(0);
// Max time interval between two trials.
static constexpr base::TimeDelta kMaxInterval = base::Minutes(1);
explicit TrialScheduler(EventDispatcher* dispatcher);
~TrialScheduler();
// Schedules a new trial with the exponential backoff strategy. Returns false
// and does nothing if there is already a pending trial scheduled.
bool ScheduleTrial(base::OnceClosure trial);
// Cancels the scheduled trial if exists. The interval between the last trial
// and the next trial won't be affected.
void CancelTrial();
// Returns true if a trial is scheduled but hasn't been executed.
bool IsTrialScheduled() const;
// Resets the interval to 0. The next scheduled trial will be executed
// immediately. It doesn't affect the pending trial if it exists.
void ResetInterval();
private:
// Executes the scheduled trial.
void ExecuteTrial();
// Updates the interval of the next trial.
void UpdateNextInterval();
// Calculates the delay of the next trial from now.
base::TimeDelta GetNextTrialDelay() const;
// Used to execute the trial in delay.
EventDispatcher* dispatcher_;
// The scheduled trial.
base::OnceClosure trial_;
// Timestamp updated when ExecuteTrial() runs.
base::TimeTicks last_trial_start_time_;
// The interval between the last trial and the next trial.
base::TimeDelta next_interval_;
base::WeakPtrFactory<TrialScheduler> weak_ptr_factory_{this};
};
} // namespace shill
#endif // SHILL_NETWORK_TRIAL_SCHEDULER_H_