folly/folly/stop_watch.h

/*
 * Copyright (c) Meta Platforms, Inc. and affiliates.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#pragma once

#include <chrono>
#include <stdexcept>
#include <utility>

#include <folly/Chrono.h>
#include <folly/Utility.h>
#include <folly/portability/Time.h>

namespace folly {

monotonic_clock;

/**
 * Calculates the duration of time intervals. Prefer this over directly using
 * monotonic clocks. It is very lightweight and provides convenient facilities
 * to avoid common pitfalls.
 *
 * There are two type aliases that should be preferred over instantiating this
 * class directly: `coarse_stop_watch` and `stop_watch`.
 *
 * Arguments:
 *  - Clock: the monotonic clock to use when calculating time intervals
 *  - Duration: (optional) the duration to use when reporting elapsed time.
 *              Defaults to the clock's duration.
 *
 * Example 1:
 *
 *  coarse_stop_watch<std::chrono::seconds> watch;
 *  do_something();
 *  std::cout << "time elapsed: " << watch.elapsed().count() << std::endl;
 *
 *  auto const ttl = 60_s;
 *  if (watch.elapsed(ttl)) {
 *    process_expiration();
 *  }
 *
 * Example 2:
 *
 *  struct run_every_n_seconds {
 *    using callback = std::function<void()>;
 *    run_every_n_seconds(std::chrono::seconds period, callback action)
 *      period_(period),
 *      action_(std::move(action))
 *    {
 *      // watch_ is correctly initialized to the current time
 *    }
 *
 *    void run() {
 *      while (true) {
 *        if (watch_.lap(period_)) {
 *          action_();
 *        }
 *        std::this_thread::yield();
 *      }
 *    }
 *
 *  private:
 *    stop_watch<> watch_;
 *    std::chrono::seconds period_;
 *    callback action_;
 *  };
 *
 */
template <typename Clock, typename Duration = typename Clock::duration>
struct custom_stop_watch : private detail::inheritable<Clock> {};

/**
 * A type alias for `custom_stop_watch` that uses a coarse monotonic clock as
 * the time source.  Refer to the documentation of `custom_stop_watch` for full
 * documentation.
 *
 * Arguments:
 *  - Duration: (optional) the duration to use when reporting elapsed time.
 *              Defaults to the clock's duration.
 *
 * Example:
 *
 *  coarse_stop_watch<std::chrono::seconds> watch;
 *  do_something();
 *  std::cout << "time elapsed: " << watch.elapsed().count() << std::endl;
 *
 */
coarse_stop_watch;

/**
 * A type alias for `custom_stop_watch` that uses a monotonic clock as the time
 * source.  Refer to the documentation of `custom_stop_watch` for full
 * documentation.
 *
 * Arguments:
 *  - Duration: (optional) the duration to use when reporting elapsed time.
 *              Defaults to the clock's duration.
 *
 * Example:
 *
 *  stop_watch<std::chrono::seconds> watch;
 *  do_something();
 *  std::cout << "time elapsed: " << watch.elapsed().count() << std::endl;
 *
 */
stop_watch;
} // namespace folly