Seastar
High performance C++ framework for concurrent servers
lowres_clock.hh
1 /*
2  * This file is open source software, licensed to you under the terms
3  * of the Apache License, Version 2.0 (the "License"). See the NOTICE file
4  * distributed with this work for additional information regarding copyright
5  * ownership. You may not use this file except in compliance with the License.
6  *
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,
12  * software distributed under the License is distributed on an
13  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14  * KIND, either express or implied. See the License for the
15  * specific language governing permissions and limitations
16  * under the License.
17  */
18 /*
19  * Copyright (C) 2016 ScyllaDB
20  */
21 
22 #pragma once
23 
24 #include <seastar/core/cacheline.hh>
25 #include <seastar/core/timer.hh>
26 
27 #include <cstdint>
28 
29 #include <atomic>
30 #include <chrono>
31 
32 namespace seastar {
33 
34 //
35 // Forward declarations.
36 //
37 
38 class lowres_clock;
39 class lowres_system_clock;
40 
42 
43 class lowres_clock_impl final {
44 public:
45  using base_steady_clock = std::chrono::steady_clock;
46  using base_system_clock = std::chrono::system_clock;
47 
48  // The clocks' resolutions are 10 ms. However, to make it is easier to do calculations with
49  // `std::chrono::milliseconds`, we make the clock period 1 ms instead of 10 ms.
50  using period = std::ratio<1, 1000>;
51 
52  using steady_rep = base_steady_clock::rep;
53  using steady_duration = std::chrono::duration<steady_rep, period>;
54  using steady_time_point = std::chrono::time_point<lowres_clock, steady_duration>;
55 
56  using system_rep = base_system_clock::rep;
57  using system_duration = std::chrono::duration<system_rep, period>;
58  using system_time_point = std::chrono::time_point<lowres_system_clock, system_duration>;
59 
60  static steady_time_point steady_now() noexcept {
61  auto const nr = counters::_steady_now.load(std::memory_order_relaxed);
62  return steady_time_point(steady_duration(nr));
63  }
64 
65  static system_time_point system_now() noexcept {
66  auto const nr = counters::_system_now.load(std::memory_order_relaxed);
67  return system_time_point(system_duration(nr));
68  }
69 
70  // For construction.
71  friend class smp;
72 private:
73  // Both counters are updated by cpu0 and read by other cpus. Place them on their own cache line to avoid false
74  // sharing.
75  struct alignas(seastar::cache_line_size) counters final {
76  static std::atomic<steady_rep> _steady_now;
77  static std::atomic<system_rep> _system_now;
78  };
79 
80  // The timer expires every 10 ms.
81  static constexpr std::chrono::milliseconds _granularity{10};
82 
83  // High-resolution timer to drive these low-resolution clocks.
84  timer<> _timer{};
85 
86  static void update() noexcept;
87 
88  // Private to ensure that static variables are only initialized once.
89  // might throw when arming timer.
90  lowres_clock_impl();
91 };
92 
94 
95 //
106 class lowres_clock final {
107 public:
108  using rep = lowres_clock_impl::steady_rep;
109  using period = lowres_clock_impl::period;
110  using duration = lowres_clock_impl::steady_duration;
111  using time_point = lowres_clock_impl::steady_time_point;
112 
113  static constexpr bool is_steady = true;
114 
118  static time_point now() noexcept {
119  return lowres_clock_impl::steady_now();
120  }
121 };
122 
132 class lowres_system_clock final {
133 public:
134  using rep = lowres_clock_impl::system_rep;
135  using period = lowres_clock_impl::period;
136  using duration = lowres_clock_impl::system_duration;
137  using time_point = lowres_clock_impl::system_time_point;
138 
139  static constexpr bool is_steady = lowres_clock_impl::base_system_clock::is_steady;
140 
144  static time_point now() noexcept {
145  return lowres_clock_impl::system_now();
146  }
147 
148  static std::time_t to_time_t(time_point t) noexcept {
149  return std::chrono::duration_cast<std::chrono::seconds>(t.time_since_epoch()).count();
150  }
151 
152  static time_point from_time_t(std::time_t t) noexcept {
153  return time_point(std::chrono::duration_cast<duration>(std::chrono::seconds(t)));
154  }
155 };
156 
157 extern template class timer<lowres_clock>;
158 
159 }
160 
seastar::lowres_system_clock
Low-resolution and efficient system clock.
Definition: lowres_clock.hh:132
seastar::lowres_system_clock::now
static time_point now() noexcept
Definition: lowres_clock.hh:144
seastar
Seastar API namespace.
Definition: abort_on_ebadf.hh:24
seastar::lowres_clock::now
static time_point now() noexcept
Definition: lowres_clock.hh:118
seastar::lowres_clock
Low-resolution and efficient steady clock.
Definition: lowres_clock.hh:106
timer.hh