NVIDIA DeepStream SDK API Reference

9.2 Release
includes/opentelemetry/common/spin_lock_mutex.h
Go to the documentation of this file.
1 // Copyright The OpenTelemetry Authors
2 // SPDX-License-Identifier: Apache-2.0
3 
4 #pragma once
5 
6 #include <atomic>
7 #include <chrono>
8 #include <thread>
9 
10 #include "opentelemetry/version.h"
11 
12 #if defined(_MSC_VER)
13 # define _WINSOCKAPI_ // stops including winsock.h
14 # include <windows.h>
15 #elif defined(__i386__) || defined(__x86_64__)
16 # if defined(__clang__)
17 # include <emmintrin.h>
18 # elif defined(__INTEL_COMPILER)
19 # include <immintrin.h>
20 # endif
21 #endif
22 
24 namespace common
25 {
26 
27 constexpr int SPINLOCK_FAST_ITERATIONS = 100;
28 constexpr int SPINLOCK_SLEEP_MS = 1;
29 
53 {
54 public:
55  SpinLockMutex() noexcept {}
56  ~SpinLockMutex() noexcept = default;
57  SpinLockMutex(const SpinLockMutex &) = delete;
58  SpinLockMutex &operator=(const SpinLockMutex &) = delete;
59 
60  static inline void fast_yield() noexcept
61  {
62 // Issue a Pause/Yield instruction while spinning.
63 #if defined(_MSC_VER)
64  YieldProcessor();
65 #elif defined(__i386__) || defined(__x86_64__)
66 # if defined(__clang__) || defined(__INTEL_COMPILER)
67  _mm_pause();
68 # else
69  __builtin_ia32_pause();
70 # endif
71 #elif defined(__armel__) || defined(__ARMEL__)
72  asm volatile("nop" ::: "memory");
73 #elif defined(__arm__) || defined(__aarch64__) // arm big endian / arm64
74  __asm__ __volatile__("yield" ::: "memory");
75 #else
76  // TODO: Issue PAGE/YIELD on other architectures.
77 #endif
78  }
79 
83  bool try_lock() noexcept
84  {
85  return !flag_.load(std::memory_order_relaxed) &&
86  !flag_.exchange(true, std::memory_order_acquire);
87  }
88 
96  void lock() noexcept
97  {
98  for (;;)
99  {
100  // Try once
101  if (!flag_.exchange(true, std::memory_order_acquire))
102  {
103  return;
104  }
105  // Spin-Fast (goal ~10ns)
106  for (std::size_t i = 0; i < SPINLOCK_FAST_ITERATIONS; ++i)
107  {
108  if (try_lock())
109  {
110  return;
111  }
112  fast_yield();
113  }
114  // Yield then try again (goal ~100ns)
115  std::this_thread::yield();
116  if (try_lock())
117  {
118  return;
119  }
120  // Sleep and then start the whole process again. (goal ~1000ns)
121  std::this_thread::sleep_for(std::chrono::milliseconds(SPINLOCK_SLEEP_MS));
122  }
123  return;
124  }
126  void unlock() noexcept { flag_.store(false, std::memory_order_release); }
127 
128 private:
129  std::atomic<bool> flag_{false};
130 };
131 
132 } // namespace common
common::SPINLOCK_SLEEP_MS
constexpr int SPINLOCK_SLEEP_MS
Definition: includes/opentelemetry/common/spin_lock_mutex.h:28
OPENTELEMETRY_BEGIN_NAMESPACE
#define OPENTELEMETRY_BEGIN_NAMESPACE
Definition: includes/opentelemetry/version.h:21
common::SpinLockMutex
A Mutex which uses atomic flags and spin-locks instead of halting threads.
Definition: includes/opentelemetry/common/spin_lock_mutex.h:52
common::SPINLOCK_FAST_ITERATIONS
constexpr int SPINLOCK_FAST_ITERATIONS
Definition: includes/opentelemetry/common/spin_lock_mutex.h:27
OPENTELEMETRY_END_NAMESPACE
#define OPENTELEMETRY_END_NAMESPACE
Definition: includes/opentelemetry/version.h:24
common::SpinLockMutex::lock
void lock() noexcept
Blocks until a lock can be obtained for the current thread.
Definition: includes/opentelemetry/common/spin_lock_mutex.h:96
common::SpinLockMutex::SpinLockMutex
SpinLockMutex() noexcept
Definition: includes/opentelemetry/common/spin_lock_mutex.h:55
common::SpinLockMutex::~SpinLockMutex
~SpinLockMutex() noexcept=default
common::SpinLockMutex::unlock
void unlock() noexcept
Releases the lock held by the execution agent.
Definition: includes/opentelemetry/common/spin_lock_mutex.h:126
common::SpinLockMutex::fast_yield
static void fast_yield() noexcept
Definition: includes/opentelemetry/common/spin_lock_mutex.h:60
common::SpinLockMutex::try_lock
bool try_lock() noexcept
Attempts to lock the mutex.
Definition: includes/opentelemetry/common/spin_lock_mutex.h:83
common
Definition: includes/opentelemetry/common/attribute_value.h:14