summaryrefslogtreecommitdiff
path: root/src/common
diff options
context:
space:
mode:
Diffstat (limited to 'src/common')
-rw-r--r--src/common/ring_buffer.h21
-rw-r--r--src/common/scope_exit.h6
-rw-r--r--src/common/string_util.cpp14
3 files changed, 16 insertions, 25 deletions
diff --git a/src/common/ring_buffer.h b/src/common/ring_buffer.h
index 138fa0131..4a8d09806 100644
--- a/src/common/ring_buffer.h
+++ b/src/common/ring_buffer.h
@@ -19,15 +19,14 @@ namespace Common {
19/// SPSC ring buffer 19/// SPSC ring buffer
20/// @tparam T Element type 20/// @tparam T Element type
21/// @tparam capacity Number of slots in ring buffer 21/// @tparam capacity Number of slots in ring buffer
22/// @tparam granularity Slot size in terms of number of elements 22template <typename T, std::size_t capacity>
23template <typename T, std::size_t capacity, std::size_t granularity = 1>
24class RingBuffer { 23class RingBuffer {
25 /// A "slot" is made of `granularity` elements of `T`. 24 /// A "slot" is made of a single `T`.
26 static constexpr std::size_t slot_size = granularity * sizeof(T); 25 static constexpr std::size_t slot_size = sizeof(T);
27 // T must be safely memcpy-able and have a trivial default constructor. 26 // T must be safely memcpy-able and have a trivial default constructor.
28 static_assert(std::is_trivial_v<T>); 27 static_assert(std::is_trivial_v<T>);
29 // Ensure capacity is sensible. 28 // Ensure capacity is sensible.
30 static_assert(capacity < std::numeric_limits<std::size_t>::max() / 2 / granularity); 29 static_assert(capacity < std::numeric_limits<std::size_t>::max() / 2);
31 static_assert((capacity & (capacity - 1)) == 0, "capacity must be a power of two"); 30 static_assert((capacity & (capacity - 1)) == 0, "capacity must be a power of two");
32 // Ensure lock-free. 31 // Ensure lock-free.
33 static_assert(std::atomic_size_t::is_always_lock_free); 32 static_assert(std::atomic_size_t::is_always_lock_free);
@@ -47,7 +46,7 @@ public:
47 const std::size_t second_copy = push_count - first_copy; 46 const std::size_t second_copy = push_count - first_copy;
48 47
49 const char* in = static_cast<const char*>(new_slots); 48 const char* in = static_cast<const char*>(new_slots);
50 std::memcpy(m_data.data() + pos * granularity, in, first_copy * slot_size); 49 std::memcpy(m_data.data() + pos, in, first_copy * slot_size);
51 in += first_copy * slot_size; 50 in += first_copy * slot_size;
52 std::memcpy(m_data.data(), in, second_copy * slot_size); 51 std::memcpy(m_data.data(), in, second_copy * slot_size);
53 52
@@ -74,7 +73,7 @@ public:
74 const std::size_t second_copy = pop_count - first_copy; 73 const std::size_t second_copy = pop_count - first_copy;
75 74
76 char* out = static_cast<char*>(output); 75 char* out = static_cast<char*>(output);
77 std::memcpy(out, m_data.data() + pos * granularity, first_copy * slot_size); 76 std::memcpy(out, m_data.data() + pos, first_copy * slot_size);
78 out += first_copy * slot_size; 77 out += first_copy * slot_size;
79 std::memcpy(out, m_data.data(), second_copy * slot_size); 78 std::memcpy(out, m_data.data(), second_copy * slot_size);
80 79
@@ -84,9 +83,9 @@ public:
84 } 83 }
85 84
86 std::vector<T> Pop(std::size_t max_slots = ~std::size_t(0)) { 85 std::vector<T> Pop(std::size_t max_slots = ~std::size_t(0)) {
87 std::vector<T> out(std::min(max_slots, capacity) * granularity); 86 std::vector<T> out(std::min(max_slots, capacity));
88 const std::size_t count = Pop(out.data(), out.size() / granularity); 87 const std::size_t count = Pop(out.data(), out.size());
89 out.resize(count * granularity); 88 out.resize(count);
90 return out; 89 return out;
91 } 90 }
92 91
@@ -113,7 +112,7 @@ private:
113 alignas(128) std::atomic_size_t m_write_index{0}; 112 alignas(128) std::atomic_size_t m_write_index{0};
114#endif 113#endif
115 114
116 std::array<T, granularity * capacity> m_data; 115 std::array<T, capacity> m_data;
117}; 116};
118 117
119} // namespace Common 118} // namespace Common
diff --git a/src/common/scope_exit.h b/src/common/scope_exit.h
index fa46cb394..35dac3a8f 100644
--- a/src/common/scope_exit.h
+++ b/src/common/scope_exit.h
@@ -49,3 +49,9 @@ ScopeExitHelper<Func> ScopeExit(Func&& func) {
49 * \endcode 49 * \endcode
50 */ 50 */
51#define SCOPE_EXIT(body) auto CONCAT2(scope_exit_helper_, __LINE__) = detail::ScopeExit([&]() body) 51#define SCOPE_EXIT(body) auto CONCAT2(scope_exit_helper_, __LINE__) = detail::ScopeExit([&]() body)
52
53/**
54 * This macro is similar to SCOPE_EXIT, except the object is caller managed. This is intended to be
55 * used when the caller might want to cancel the ScopeExit.
56 */
57#define SCOPE_GUARD(body) detail::ScopeExit([&]() body)
diff --git a/src/common/string_util.cpp b/src/common/string_util.cpp
index 4cba2aaa4..7b614ad89 100644
--- a/src/common/string_util.cpp
+++ b/src/common/string_util.cpp
@@ -141,27 +141,13 @@ std::string ReplaceAll(std::string result, const std::string& src, const std::st
141} 141}
142 142
143std::string UTF16ToUTF8(const std::u16string& input) { 143std::string UTF16ToUTF8(const std::u16string& input) {
144#ifdef _MSC_VER
145 // Workaround for missing char16_t/char32_t instantiations in MSVC2017
146 std::wstring_convert<std::codecvt_utf8_utf16<__int16>, __int16> convert;
147 std::basic_string<__int16> tmp_buffer(input.cbegin(), input.cend());
148 return convert.to_bytes(tmp_buffer);
149#else
150 std::wstring_convert<std::codecvt_utf8_utf16<char16_t>, char16_t> convert; 144 std::wstring_convert<std::codecvt_utf8_utf16<char16_t>, char16_t> convert;
151 return convert.to_bytes(input); 145 return convert.to_bytes(input);
152#endif
153} 146}
154 147
155std::u16string UTF8ToUTF16(const std::string& input) { 148std::u16string UTF8ToUTF16(const std::string& input) {
156#ifdef _MSC_VER
157 // Workaround for missing char16_t/char32_t instantiations in MSVC2017
158 std::wstring_convert<std::codecvt_utf8_utf16<__int16>, __int16> convert;
159 auto tmp_buffer = convert.from_bytes(input);
160 return std::u16string(tmp_buffer.cbegin(), tmp_buffer.cend());
161#else
162 std::wstring_convert<std::codecvt_utf8_utf16<char16_t>, char16_t> convert; 149 std::wstring_convert<std::codecvt_utf8_utf16<char16_t>, char16_t> convert;
163 return convert.from_bytes(input); 150 return convert.from_bytes(input);
164#endif
165} 151}
166 152
167#ifdef _WIN32 153#ifdef _WIN32