userver: userver/concurrent/impl/tagged_ptr.hpp Source File
⚠️ This is the documentation for an old userver version. Click here to switch to the latest version.
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages Concepts
tagged_ptr.hpp
1#pragma once
2
3#include <atomic>
4#include <cstdint>
5
6#include <userver/utils/assert.hpp>
7
8USERVER_NAMESPACE_BEGIN
9
10namespace concurrent::impl {
11
12template <typename T>
13class TaggedPtr final {
14 static_assert(sizeof(std::uintptr_t) <= sizeof(std::uint64_t));
15 static constexpr std::uint64_t kTagShift = 48;
16
17 public:
18 using Tag = std::uint16_t;
19
20 constexpr /*implicit*/ TaggedPtr(std::nullptr_t) noexcept : impl_(0) {}
21
22 TaggedPtr(T* ptr, Tag tag)
23 : impl_(reinterpret_cast<std::uintptr_t>(ptr) |
24 (std::uint64_t{tag} << kTagShift)) {
25 UASSERT(!(reinterpret_cast<std::uintptr_t>(ptr) & 0xffff'0000'0000'0000));
26 }
27
28 T* GetDataPtr() const noexcept {
29 return reinterpret_cast<T*>(static_cast<std::uintptr_t>(
30 impl_ & ((std::uint64_t{1} << kTagShift) - 1)));
31 }
32
33 Tag GetTag() const noexcept { return static_cast<Tag>(impl_ >> kTagShift); }
34
35 Tag GetNextTag() const noexcept { return static_cast<Tag>(GetTag() + 1); }
36
37 private:
38 std::uint64_t impl_;
39};
40
41} // namespace concurrent::impl
42
43USERVER_NAMESPACE_END