userver: userver/utils/statistics/busy.hpp Source File
Loading...
Searching...
No Matches
busy.hpp
1#pragma once
2
3#include <memory>
4
5#include <userver/utils/statistics/recentperiod.hpp>
6
7USERVER_NAMESPACE_BEGIN
8
9namespace utils::statistics {
10
11using Duration = std::chrono::steady_clock::duration;
12
13/* Storage of how much time we've spent in work recently, in %.
14 * 'max_workers' limits number of threads working at the same time. */
15class BusyStorage final {
16 public:
17 BusyStorage(Duration epoch_duration, Duration history_period,
18 size_t max_workers = 1);
19
20 ~BusyStorage();
21
22 double GetCurrentLoad() const;
23
24 using WorkerId = size_t;
25
26 WorkerId StartWork();
27
28 void StopWork(WorkerId worker_id);
29
30 private:
31 WorkerId PopWorkerId();
32
33 Duration GetNotCommittedLoad(WorkerId worker_id) const;
34
35 bool IsAlreadyStarted() const;
36
37 bool UpdateCurrentWorkerLoad(std::vector<Duration>& load) const;
38
39 struct Impl;
40 std::unique_ptr<Impl> pimpl;
41
42 friend class BusyMarker;
43};
44
45/* A RAII-style guard to account code block execution time in BusyStorage.
46 * It is reentrant, IOW you may create BusyMarker inside of another BusyMarker
47 * and work time is accounted correctly (based on the outer BusyMarker
48 * lifetime).
49 */
50class BusyMarker final {
51 public:
52 BusyMarker(BusyStorage& storage)
53 : storage_(storage), worker_id_(storage.StartWork()) {}
54
55 BusyMarker(const BusyMarker&) = delete;
56 BusyMarker& operator=(const BusyMarker&) = delete;
57
58 ~BusyMarker() { storage_.StopWork(worker_id_); }
59
60 private:
61 BusyStorage& storage_;
62 BusyStorage::WorkerId worker_id_;
63};
64
65} // namespace utils::statistics
66
67USERVER_NAMESPACE_END