Lagrange
control_block.h
1// Source: https://github.com/X-czh/smart_ptr
2// SPDX-License-Identifier: MIT
3//
4// This file has been modified by Adobe.
5//
6// All modifications are Copyright 2022 Adobe.
7
8// control_block implementation
9
10#pragma once
11
12#include <lagrange/internal/smart_ptr/default_delete.h>
13#include <lagrange/internal/smart_ptr/ptr.h>
14
15#include <atomic> // atomic
16#include <memory> // allocator, addressof
17
18namespace lagrange::internal {
19
20// control block interface
21// Type erasure for storing deleter and allocators
22
24{
25public:
26 virtual ~control_block_base(){};
27
28 virtual void inc_ref() noexcept = 0;
29 virtual void inc_wref() noexcept = 0;
30 virtual void dec_ref() noexcept = 0;
31 virtual void dec_wref() noexcept = 0;
32
33 virtual long use_count() const noexcept = 0;
34 virtual bool unique() const noexcept = 0;
35 virtual long weak_use_count() const noexcept = 0;
36 virtual bool expired() const noexcept = 0;
37
38 virtual void* get_deleter() noexcept = 0;
39};
40
41// control block for reference counting of shared_ptr and weak_ptr
42
50template <typename T, typename D = default_delete<T>>
52{
53public:
54 using element_type = T;
55 using deleter_type = D;
56
57 // Constructors
58
59 control_block(T* p)
60 : _impl{p}
61 {}
62
63 control_block(T* p, D d)
64 : _impl{p, d}
65 {}
66
67
68 // Destructor
69
70 ~control_block() = default;
71
72 // Modifiers
73
74 void inc_ref() noexcept override { ++_use_count; }
75
76 void inc_wref() noexcept override { ++_weak_use_count; }
77
78 void dec_ref() noexcept override
79 {
80 auto _ptr = _impl._impl_ptr();
81 auto& _deleter = _impl._impl_deleter();
82 if (--_use_count == 0) {
83 if (_ptr) _deleter(_ptr); // destroy the object _ptr points to
84 dec_wref();
85 }
86 }
87
88 void dec_wref() noexcept override
89 {
90 if (--_weak_use_count == 0) {
91 delete this; // destroy control_block itself
92 }
93 }
94
95 // Observers
96
97 long use_count() const noexcept override // Returns #shared_ptr
98 {
99 return _use_count;
100 }
101
102 bool unique() const noexcept override { return _use_count == 1; }
103
104 long weak_use_count() const noexcept override // Returns #weak_ptr
105 {
106 return _weak_use_count - ((_use_count > 0) ? 1 : 0);
107 }
108
109 bool expired() const noexcept override { return _use_count == 0; }
110
111 void* get_deleter() noexcept override // Type erasure for storing deleter
112 {
113 return reinterpret_cast<void*>(std::addressof(_impl._impl_deleter()));
114 }
115
116private:
117 std::atomic<long> _use_count{1};
118
119 // Note: _weak_use_count = #weak_ptrs + (#shared_ptr > 0) ? 1 : 0
120 std::atomic<long> _weak_use_count{1};
121
122 ptr<T, D> _impl;
123};
124
125} // namespace lagrange::internal
Definition: control_block.h:24
NOT implemented: custom allocator support.
Definition: control_block.h:52
Definition: ptr.h:18
nullptr_t, size_t, ptrdiff_t basic_ostream bad_weak_ptr extent, remove_extent, is_array,...
Definition: attribute_string_utils.h:21