PMDK C++ bindings 1.13.0
This is the C++ bindings documentation for PMDK's libpmemobj.
atomic_backoff.hpp
Go to the documentation of this file.
1// SPDX-License-Identifier: BSD-3-Clause
2/* Copyright 2019-2020, Intel Corporation */
3
13#ifndef LIBPMEMOBJ_ATOMIC_BACKOFF_HPP
14#define LIBPMEMOBJ_ATOMIC_BACKOFF_HPP
15
16#include <thread>
17
18#if _MSC_VER
19#include <intrin.h>
20#include <windows.h>
21#endif
22
23namespace pmem
24{
25namespace detail
26{
27
28class atomic_backoff {
34 static const int32_t LOOPS_BEFORE_YIELD = 16;
35 int32_t count;
36
37 static inline void
38 __pause(int32_t delay)
39 {
40 for (; delay > 0; --delay) {
41#if _MSC_VER
42 YieldProcessor();
43#elif __GNUC__ && (__i386__ || __x86_64__)
44 // Only i386 and x86-64 have pause instruction
45 __builtin_ia32_pause();
46#endif
47 }
48 }
49
50public:
54 atomic_backoff(const atomic_backoff &) = delete;
58 atomic_backoff &operator=(const atomic_backoff &) = delete;
59
61 /* In many cases, an object of this type is initialized eagerly on hot
62 * path, as in for(atomic_backoff b; ; b.pause()) {...} For this reason,
63 * the construction cost must be very small! */
64 atomic_backoff() : count(1)
65 {
66 }
67
71 atomic_backoff(bool) : count(1)
72 {
73 pause();
74 }
75
79 void
80 pause()
81 {
82 if (count <= LOOPS_BEFORE_YIELD) {
83 __pause(count);
84 /* Pause twice as long the next time. */
85 count *= 2;
86 } else {
87 /* Pause is so long that we might as well yield CPU to
88 * scheduler. */
89 std::this_thread::yield();
90 }
91 }
92
96 bool
97 bounded_pause()
98 {
99 __pause(count);
100 if (count < LOOPS_BEFORE_YIELD) {
101 /* Pause twice as long the next time. */
102 count *= 2;
103 return true;
104 } else {
105 return false;
106 }
107 }
108
109 void
110 reset()
111 {
112 count = 1;
113 }
114}; /* class atomic_backoff */
115
116} /* namespace detail */
117
118} /* namespace pmem */
119
120#endif
Persistent memory namespace.
Definition: allocation_flag.hpp:15