userver: userver/concurrent/impl/tagged_ptr.hpp Source File
Loading...
Searching...
No Matches
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