]> git.proxmox.com Git - ceph.git/blob - ceph/src/rocksdb/third-party/folly/folly/synchronization/detail/Spin.h
buildsys: change download over to reef release
[ceph.git] / ceph / src / rocksdb / third-party / folly / folly / synchronization / detail / Spin.h
1 // Copyright (c) 2011-present, Facebook, Inc. All rights reserved.
2 // This source code is licensed under both the GPLv2 (found in the
3 // COPYING file in the root directory) and Apache 2.0 License
4 // (found in the LICENSE.Apache file in the root directory).
5
6 #pragma once
7
8 #include <algorithm>
9 #include <chrono>
10 #include <thread>
11
12 #include <folly/portability/Asm.h>
13 #include <folly/synchronization/WaitOptions.h>
14
15 namespace folly {
16 namespace detail {
17
18 enum class spin_result {
19 success, // condition passed
20 timeout, // exceeded deadline
21 advance, // exceeded current wait-options component timeout
22 };
23
24 template <typename Clock, typename Duration, typename F>
25 spin_result spin_pause_until(
26 std::chrono::time_point<Clock, Duration> const& deadline,
27 WaitOptions const& opt,
28 F f) {
29 if (opt.spin_max() <= opt.spin_max().zero()) {
30 return spin_result::advance;
31 }
32
33 auto tbegin = Clock::now();
34 while (true) {
35 if (f()) {
36 return spin_result::success;
37 }
38
39 auto const tnow = Clock::now();
40 if (tnow >= deadline) {
41 return spin_result::timeout;
42 }
43
44 // Backward time discontinuity in Clock? revise pre_block starting point
45 tbegin = std::min(tbegin, tnow);
46 if (tnow >= tbegin + opt.spin_max()) {
47 return spin_result::advance;
48 }
49
50 // The pause instruction is the polite way to spin, but it doesn't
51 // actually affect correctness to omit it if we don't have it. Pausing
52 // donates the full capabilities of the current core to its other
53 // hyperthreads for a dozen cycles or so.
54 asm_volatile_pause();
55 }
56 }
57
58 template <typename Clock, typename Duration, typename F>
59 spin_result spin_yield_until(
60 std::chrono::time_point<Clock, Duration> const& deadline,
61 F f) {
62 while (true) {
63 if (f()) {
64 return spin_result::success;
65 }
66
67 auto const max = std::chrono::time_point<Clock, Duration>::max();
68 if (deadline != max && Clock::now() >= deadline) {
69 return spin_result::timeout;
70 }
71
72 std::this_thread::yield();
73 }
74 }
75
76 } // namespace detail
77 } // namespace folly