NexusForce 1.0.0
A rigorously engineered full-stack C++ backend library.
载入中...
搜索中...
未找到
shared_ptr.hpp
浏览该文件的文档.
1#ifndef NEFORCE_CORE_MEMORY_SHARED_PTR_HPP__
2#define NEFORCE_CORE_MEMORY_SHARED_PTR_HPP__
3
11
12#include <new>
18NEFORCE_BEGIN_NAMESPACE__
19
25
27NEFORCE_BEGIN_INNER__
28
29template <typename T>
30class smart_pointer_atomic;
31
32
39struct __smart_ptr_counter {
40public:
41 atomic<unsigned long> strong_count_;
42 atomic<unsigned long> weak_count_;
43
44protected:
48 virtual void delete_object() = 0;
49
53 virtual void delete_this() = 0;
54
55public:
60 __smart_ptr_counter() noexcept :
61 strong_count_(1),
62 weak_count_(1) {}
63
64 __smart_ptr_counter(__smart_ptr_counter&&) = delete;
65
66 virtual ~__smart_ptr_counter() = default;
67
71 void incref_strong() noexcept { strong_count_.fetch_add(1, memory_order_relaxed); }
72
76 void incref_weak() noexcept { weak_count_.fetch_add(1, memory_order_relaxed); }
77
82 void decref_strong() noexcept {
83 if (strong_count_.fetch_sub(1, memory_order_acq_rel) == 1) {
84 delete_object();
85 decref_weak();
86 }
87 }
88
93 void decref_weak() noexcept {
94 if (weak_count_.fetch_sub(1, memory_order_acq_rel) == 1) {
95 delete_this();
96 }
97 }
98
105 bool try_incref_strong() noexcept {
106 auto strong = strong_count_.load(memory_order_relaxed);
107 do {
108 if (strong == 0) {
109 return false;
110 }
111 } while (!strong_count_.compare_exchange_weak(strong, strong + 1, memory_order_release, memory_order_relaxed));
112 return true;
113 }
114
119 NEFORCE_NODISCARD uint64_t use_count() const noexcept { return strong_count_.load(memory_order_relaxed); }
120
125 NEFORCE_NODISCARD uint64_t weak_count() const noexcept { return weak_count_.load(memory_order_relaxed); }
126};
127
135template <typename T, typename Deleter>
136struct __smart_ptr_counter_impl final : __smart_ptr_counter {
137 compressed_pair<Deleter, T*> ptr_pair_{default_construct_tag{}, nullptr};
138
139 static_assert(is_invocable_v<Deleter, T*>, "Deleter must be invocable by T*");
140
141 explicit __smart_ptr_counter_impl(T* ptr) noexcept(is_nothrow_default_constructible_v<Deleter>) :
142 ptr_pair_(default_construct_tag{}, ptr) {}
143
144 template <typename Del = Deleter, enable_if_t<is_constructible_v<Deleter, Del>, int> = 0>
145 explicit __smart_ptr_counter_impl(T* ptr, Del&& deleter) noexcept(is_nothrow_constructible_v<Deleter, Del>) :
146 ptr_pair_(exact_arg_construct_tag{}, _NEFORCE forward<Del>(deleter), ptr) {}
147
148 void delete_object() override {
149 ptr_pair_.get_base()(ptr_pair_.value);
150 ptr_pair_.value = nullptr;
151 }
152
153 void delete_this() noexcept override { delete this; }
154};
155
163template <typename T, typename Deleter>
164struct __smart_ptr_counter_impl_fused final : __smart_ptr_counter {
165 compressed_pair<Deleter, T*> ptr_pair_{default_construct_tag{}, nullptr};
166 size_t align_;
167 void* mem_;
168
169 explicit __smart_ptr_counter_impl_fused(T* ptr, void* mem, size_t align, Deleter deleter) noexcept :
170 ptr_pair_(exact_arg_construct_tag{}, _NEFORCE move(deleter), ptr),
171 align_(align),
172 mem_(mem) {}
173
174 void delete_object() noexcept override {
175 ptr_pair_.get_base()(ptr_pair_.value);
176 ptr_pair_.value = nullptr;
177 }
178
179 void delete_this() noexcept override {
180#if NEFORCE_STANDARD_17
181 operator delete(mem_, std::align_val_t{align_});
182#else
183 operator delete(mem_);
184#endif
185 }
186};
187
196template <typename T, typename Deleter, typename Alloc>
197struct __smart_ptr_counter_impl_allocated final : __smart_ptr_counter {
198 compressed_pair<Deleter, T*> ptr_pair_{default_construct_tag{}, nullptr};
199 compressed_pair<Alloc, size_t> size_pair_{default_construct_tag{}, 0};
200 void* mem_;
201
202 explicit __smart_ptr_counter_impl_allocated(T* ptr, void* mem, const size_t size, Deleter deleter,
203 Alloc alloc) noexcept :
204 ptr_pair_(exact_arg_construct_tag{}, _NEFORCE move(deleter), ptr),
205 size_pair_(exact_arg_construct_tag{}, _NEFORCE move(alloc), size),
206 mem_(mem) {}
207
208 void delete_object() noexcept override {
209 ptr_pair_.get_base()(ptr_pair_.value);
210 ptr_pair_.value = nullptr;
211 }
212
213 void delete_this() noexcept override {
214 using alloc_traits = allocator_traits<Alloc>;
215 using byte_allocator = typename alloc_traits::template alloc_rebind_t<Alloc, byte_t>;
216 byte_allocator byte_alloc(size_pair_.get_base());
217 allocator_traits<byte_allocator>::deallocate(byte_alloc, static_cast<byte_t*>(mem_), size_pair_.value);
218 }
219};
220
221NEFORCE_END_INNER__
223
224
225template <typename T>
226struct enable_shared_from_this;
227
228template <typename T>
229class shared_ptr;
230
231template <typename T>
232class weak_ptr;
233
235NEFORCE_BEGIN_INNER__
236
237template <typename T>
238void __setup_enable_shared_from_impl(T* ptr, __smart_ptr_counter* owner, true_type /*unused*/) noexcept {
239 if (ptr) {
240 static_cast<enable_shared_from_this<T>*>(ptr)->owner_ = owner;
241 }
242}
243
244template <typename T>
245void __setup_enable_shared_from_impl(T* /*unused*/, __smart_ptr_counter* /*unused*/, false_type /*unused*/) noexcept {}
246
247template <typename T>
248void __setup_enable_shared_from(T* ptr, __smart_ptr_counter* owner) noexcept {
249 inner::__setup_enable_shared_from_impl(ptr, owner, is_base_of<enable_shared_from_this<T>, T>{});
250}
251
252template <typename T>
253shared_ptr<T> __make_shared_fused(T* ptr, __smart_ptr_counter* owner) noexcept {
254 return shared_ptr<T>(ptr, owner);
255}
256
257NEFORCE_END_INNER__
259
260
269template <typename T>
270class shared_ptr {
271public:
272 using element_type = T;
273
274private:
275 using owner_type = inner::__smart_ptr_counter;
276
277 template <typename U, typename Deleter>
278 using owner_deleter = inner::__smart_ptr_counter_impl<U, Deleter>;
279
280 template <typename U>
281 using owner_default = inner::__smart_ptr_counter_impl<U, default_deleter<U>>;
282
283 element_type* ptr_ = nullptr;
284 owner_type* owner_ = nullptr;
285
291 explicit shared_ptr(T* ptr, owner_type* owner) noexcept :
292 ptr_(ptr),
293 owner_(owner) {}
294
295 template <typename U>
296 friend class shared_ptr;
297
298 template <typename U>
299 friend class weak_ptr;
300
301 template <typename U>
302 friend class inner::smart_pointer_atomic;
303
304 template <typename U>
305 friend shared_ptr<U> inner::__make_shared_fused(U*, inner::__smart_ptr_counter*) noexcept;
306
307public:
314 shared_ptr(nullptr_t np = nullptr) noexcept {}
315
321 template <typename U, enable_if_t<is_convertible_v<U*, T*>, int> = 0>
322 shared_ptr(U* ptr) :
323 ptr_(ptr),
324 owner_(new owner_default<U>(ptr)) {
325 inner::__setup_enable_shared_from(ptr_, owner_);
326 }
327
335 template <typename U, typename Deleter, enable_if_t<is_convertible_v<U*, T*>, int> = 0>
336 explicit shared_ptr(U* ptr, Deleter&& deleter) :
337 ptr_(ptr),
338 owner_(new owner_deleter<U, Deleter>(ptr_, _NEFORCE forward<Deleter>(deleter))) {
339 inner::__setup_enable_shared_from(ptr_, owner_);
340 }
341
348 template <typename U, typename Deleter, enable_if_t<is_convertible_v<U*, T*>, int> = 0>
350 shared_ptr(unique.release(), unique.get_deleter()) {}
351
356 shared_ptr(const shared_ptr& other) noexcept :
357 ptr_(other.ptr_),
358 owner_(other.owner_) {
359 if (owner_ != nullptr) {
360 owner_->incref_strong();
361 }
362 }
363
369 shared_ptr& operator=(const shared_ptr& other) noexcept {
370 if (_NEFORCE addressof(other) == this) {
371 return *this;
372 }
373 if (owner_ != nullptr) {
374 owner_->decref_strong();
375 }
376 ptr_ = other.ptr_;
377 owner_ = other.owner_;
378 if (owner_ != nullptr) {
379 owner_->incref_strong();
380 }
381 return *this;
382 }
383
389 template <typename U, enable_if_t<is_convertible_v<U*, T*>, int> = 0>
390 shared_ptr(const shared_ptr<U>& other) noexcept :
391 ptr_(other.ptr_),
392 owner_(other.owner_) {
393 if (owner_) {
394 owner_->incref_strong();
395 }
396 }
397
402 shared_ptr(shared_ptr&& other) noexcept :
403 ptr_(other.ptr_),
404 owner_(other.owner_) {
405 other.ptr_ = nullptr;
406 other.owner_ = nullptr;
407 }
408
414 shared_ptr& operator=(shared_ptr&& other) noexcept {
415 if (_NEFORCE addressof(other) == this) {
416 return *this;
417 }
418 if (owner_ != nullptr) {
419 owner_->decref_strong();
420 }
421 ptr_ = other.ptr_;
422 owner_ = other.owner_;
423 other.ptr_ = nullptr;
424 other.owner_ = nullptr;
425 return *this;
426 }
427
433 template <typename U, enable_if_t<is_convertible_v<U*, T*>, int> = 0>
434 explicit shared_ptr(shared_ptr<U>&& other) noexcept :
435 ptr_(other.ptr_),
436 owner_(other.owner_) {
437 other.ptr_ = nullptr;
438 other.owner_ = nullptr;
439 }
440
448 template <typename U>
449 shared_ptr(const shared_ptr<U>& other, T* ptr) noexcept :
450 ptr_(ptr),
451 owner_(other.owner_) {
452 if (owner_) {
453 owner_->incref_strong();
454 }
455 }
456
460 template <typename U>
461 shared_ptr(shared_ptr<U>&& other, T* ptr) noexcept :
462 ptr_(ptr),
463 owner_(other.owner_) {
464 other.ptr_ = nullptr;
465 other.owner_ = nullptr;
466 }
467
471 template <typename U, enable_if_t<is_convertible_v<U*, T*>, int> = 0>
472 shared_ptr& operator=(const shared_ptr<U>& other) noexcept {
473 if (owner_) {
474 owner_->decref_strong();
475 }
476 ptr_ = other.ptr_;
477 owner_ = other.owner_;
478 if (owner_) {
479 owner_->incref_strong();
480 }
481 return *this;
482 }
483
487 template <typename U, enable_if_t<is_convertible_v<U*, T*>, int> = 0>
488 shared_ptr& operator=(shared_ptr<U>&& other) noexcept {
489 if (owner_) {
490 owner_->decref_strong();
491 }
492 ptr_ = other.ptr_;
493 owner_ = other.owner_;
494 other.ptr_ = nullptr;
495 other.owner_ = nullptr;
496 return *this;
497 }
498
503 ~shared_ptr() noexcept { reset(); }
504
508 void reset() noexcept {
509 if (owner_ != nullptr) {
510 owner_->decref_strong();
511 }
512 owner_ = nullptr;
513 ptr_ = nullptr;
514 }
515
521 template <typename U>
522 void reset(U* ptr) {
523 if (owner_) {
524 owner_->decref_strong();
525 }
526 ptr_ = nullptr;
527 owner_ = nullptr;
528 ptr_ = ptr;
529 owner_ = new owner_default<U>(ptr_);
530 inner::__setup_enable_shared_from<T>(ptr_, owner_);
531 }
532
540 template <typename U, typename Deleter>
541 void reset(U* ptr, Deleter deleter) {
542 if (owner_) {
543 owner_->decref_strong();
544 }
545 ptr_ = nullptr;
546 owner_ = nullptr;
547 ptr_ = ptr;
548 owner_ = new owner_deleter<U, Deleter>(ptr_, _NEFORCE move(deleter));
549 inner::__setup_enable_shared_from<T>(ptr_, owner_);
550 }
551
556 NEFORCE_NODISCARD long use_count() const noexcept { return owner_ != nullptr ? owner_->use_count() : 0; }
557
562 NEFORCE_NODISCARD bool unique() const noexcept { return owner_ != nullptr ? owner_->use_count() == 1 : true; }
563
568 void swap(shared_ptr& other) noexcept {
569 if (_NEFORCE addressof(other) == this) {
570 return;
571 }
572 _NEFORCE swap(ptr_, other.ptr_);
573 _NEFORCE swap(owner_, other.owner_);
574 }
575
580 NEFORCE_NODISCARD T* get() const noexcept { return ptr_; }
581
586 NEFORCE_NODISCARD T* operator->() const noexcept { return ptr_; }
587
592 NEFORCE_NODISCARD add_lvalue_reference_t<T> operator*() const noexcept { return *ptr_; }
593
598 NEFORCE_NODISCARD explicit operator bool() const noexcept { return ptr_ != nullptr; }
599
606 template <typename U>
607 NEFORCE_NODISCARD bool owner_equal(const shared_ptr<U>& rhs) const noexcept {
608 return owner_ == rhs.owner_;
609 }
610
614 template <typename U>
615 NEFORCE_NODISCARD bool owner_equal(const weak_ptr<U>& rhs) const noexcept {
616 return owner_ == rhs.owner_;
617 }
618
625 template <typename U>
626 NEFORCE_NODISCARD bool owner_before(const shared_ptr<U>& rhs) const noexcept {
627 return owner_ < rhs.owner_;
628 }
629
633 template <typename U>
634 NEFORCE_NODISCARD bool owner_before(const weak_ptr<U>& rhs) const noexcept {
635 return owner_ < rhs.owner_;
636 }
637};
638
642template <typename T, typename U>
643NEFORCE_NODISCARD bool operator==(const shared_ptr<T>& lhs, const shared_ptr<U>& rhs) noexcept {
644 return lhs.owner_equal(rhs);
645}
646
650template <typename T, typename U>
651NEFORCE_NODISCARD bool operator!=(const shared_ptr<T>& lhs, const shared_ptr<U>& rhs) noexcept {
652 return !(lhs == rhs);
653}
654
658template <typename T, typename U>
659NEFORCE_NODISCARD bool operator<(const shared_ptr<T>& lhs, const shared_ptr<U>& rhs) noexcept {
660 return lhs.owner_before(rhs);
661}
662
666template <typename T, typename U>
667NEFORCE_NODISCARD bool operator>(const shared_ptr<T>& lhs, const shared_ptr<U>& rhs) noexcept {
668 return rhs < lhs;
669}
670
674template <typename T, typename U>
675NEFORCE_NODISCARD bool operator<=(const shared_ptr<T>& lhs, const shared_ptr<U>& rhs) noexcept {
676 return !(lhs > rhs);
677}
678
682template <typename T, typename U>
683NEFORCE_NODISCARD bool operator>=(const shared_ptr<T>& lhs, const shared_ptr<U>& rhs) noexcept {
684 return !(lhs < rhs);
685}
686
693template <typename T>
694NEFORCE_NODISCARD bool operator==(const shared_ptr<T>& lhs, nullptr_t np) noexcept {
695 return lhs.get() == nullptr;
696}
697
704template <typename T>
705NEFORCE_NODISCARD bool operator==(nullptr_t np, const shared_ptr<T>& rhs) noexcept {
706 return rhs.get() == nullptr;
707}
708
715template <typename T>
716NEFORCE_NODISCARD bool operator!=(const shared_ptr<T>& lhs, nullptr_t np) noexcept {
717 return lhs.get() != nullptr;
718}
719
726template <typename T>
727NEFORCE_NODISCARD bool operator!=(nullptr_t np, const shared_ptr<T>& rhs) noexcept {
728 return rhs.get() != nullptr;
729}
730
731
736template <typename T>
737class shared_ptr<T[]> : shared_ptr<T> {
738public:
739 using shared_ptr<T>::shared_ptr;
740
746 add_lvalue_reference_t<T> operator[](size_t idx) { return this->get()[idx]; }
747};
748
749
757template <typename T>
759private:
760 mutable inner::__smart_ptr_counter* owner_ = nullptr;
761
762 template <typename U>
763 friend void inner::__setup_enable_shared_from_impl(U* ptr, inner::__smart_ptr_counter* owner, true_type) noexcept;
764
765 template <typename U>
766 friend void inner::__setup_enable_shared_from(U*, inner::__smart_ptr_counter*) noexcept;
767
768 template <typename U>
769 friend class shared_ptr;
770
771 template <typename U>
772 friend class weak_ptr;
773
774protected:
778 enable_shared_from_this() noexcept = default;
779
780public:
786 shared_ptr<T> shared_from_this() {
787 static_assert(is_base_of_v<enable_shared_from_this, T>, "shared from T requires derived class");
788 if (owner_ == nullptr) {
789 NEFORCE_THROW_EXCEPTION(memory_exception("smart pointer share failed."));
790 }
791 owner_->incref_strong();
792 return inner::__make_shared_fused(static_cast<T*>(this), owner_);
793 }
794
800 shared_ptr<const T> shared_from_this() const {
801 static_assert(is_base_of_v<enable_shared_from_this, T>, "shared from T requires derived class");
802 if (owner_ == nullptr) {
803 NEFORCE_THROW_EXCEPTION(memory_exception("smart pointer share failed."));
804 }
805 owner_->incref_strong();
806 return inner::__make_shared_fused(static_cast<const T*>(this), owner_);
807 }
808
814 weak_ptr<T> weak_from_this() noexcept;
815
821 weak_ptr<const T> weak_from_this() const noexcept;
822};
823
824
828template <typename T>
830
831template <typename T>
832struct is_shared_ptr<shared_ptr<T>> : true_type {};
833
834template <typename T>
835NEFORCE_INLINE17 constexpr bool is_shared_ptr_v = is_shared_ptr<T>::value;
836
837
848template <typename T, typename... Args>
850 auto const deleter = [](T* ptr) noexcept(is_nothrow_destructible_v<T>) { ptr->~T(); };
851 using Counter = inner::__smart_ptr_counter_impl_fused<T, decltype(deleter)>;
852 constexpr size_t align = max(alignof(T), alignof(Counter));
853 constexpr size_t offset = (sizeof(Counter) + align - 1) & ~(align - 1);
854 constexpr size_t size = offset + sizeof(T);
855#if NEFORCE_STANDARD_17
856 void* mem = operator new(size, std::align_val_t{align});
857 auto* counter = static_cast<Counter*>(mem);
858#else
859 void* mem = operator new(size + align - 1);
860 size_t aligned_addr = (reinterpret_cast<size_t>(mem) + (align - 1)) & ~(align - 1);
861 Counter* counter = reinterpret_cast<Counter*>(aligned_addr);
862#endif
863 T* object = reinterpret_cast<T*>(reinterpret_cast<byte_t*>(counter) + offset);
864 try {
865 _NEFORCE construct(object, _NEFORCE forward<Args>(args)...);
866 } catch (...) {
867#if NEFORCE_STANDARD_17
868 operator delete(mem, std::align_val_t{align});
869#else
870 operator delete(mem);
871#endif
872 NEFORCE_THROW_EXCEPTION(memory_exception("shared ptr construction failed."));
873 }
874 _NEFORCE construct(reinterpret_cast<Counter*>(counter), object, mem, align, _NEFORCE move(deleter));
875 inner::__setup_enable_shared_from(object, counter);
876 return inner::__make_shared_fused(object, counter);
877}
878
886template <typename T>
888 using value = remove_extent_t<T>;
889 value* tmp = nullptr;
890 try {
891 tmp = new value[len];
892 return shared_ptr<value[]>(tmp, default_deleter<value[]>{});
893 } catch (...) {
894 operator delete[](tmp);
895 NEFORCE_THROW_EXCEPTION(memory_exception("shared ptr construction failed."));
896 }
897 unreachable();
898}
899
912template <typename T, typename Alloc, typename... Args>
914 Args&&... args) {
915 auto deleter = [](T* p) { p->~T(); };
916 using ControlBlock = inner::__smart_ptr_counter_impl_allocated<T, decltype(deleter), Alloc>;
917
918 const size_t align = _NEFORCE max(alignof(ControlBlock), alignof(T));
919 const size_t offset = (sizeof(ControlBlock) + align - 1) & ~(align - 1);
920 const size_t total_size = offset + sizeof(T);
921 const size_t raw_size = total_size + align - 1;
922
923 using alloc_traits = allocator_traits<remove_cv_t<Alloc>>;
924 using byte_allocator = typename alloc_traits::template alloc_rebind_t<Alloc, byte_t>;
925 byte_allocator byte_alloc(alloc);
926
927 byte_t* raw_mem = allocator_traits<byte_allocator>::allocate(byte_alloc, raw_size);
928
929 const auto raw_addr = reinterpret_cast<uintptr_t>(raw_mem);
930 const uintptr_t aligned_addr = (raw_addr + align - 1) & ~static_cast<uintptr_t>(align - 1);
931 auto* aligned_mem = reinterpret_cast<byte_t*>(aligned_addr);
932 T* object_ptr = reinterpret_cast<T*>(aligned_mem + offset);
933
934 try {
935 allocator_traits<Alloc>::construct(alloc, object_ptr, _NEFORCE forward<Args>(args)...);
936 } catch (...) {
937 allocator_traits<byte_allocator>::deallocate(byte_alloc, raw_mem, raw_size);
938 NEFORCE_THROW_EXCEPTION(memory_exception("shared ptr ref object construction failed."));
939 }
940
941 ControlBlock* ctrl_block = nullptr;
942 try {
943 ctrl_block = _NEFORCE construct(reinterpret_cast<ControlBlock*>(aligned_mem), object_ptr, raw_mem, raw_size,
944 deleter, alloc);
945 } catch (...) {
946 allocator_traits<Alloc>::destroy(alloc, object_ptr);
947 allocator_traits<byte_allocator>::deallocate(byte_alloc, raw_mem, raw_size);
948 NEFORCE_THROW_EXCEPTION(memory_exception("shared ptr control block construction failed."));
949 }
950
951 inner::__setup_enable_shared_from(object_ptr, ctrl_block);
952 return inner::__make_shared_fused(object_ptr, ctrl_block);
953}
954
955
963template <typename T, typename U>
965 return shared_ptr<T>(ptr, static_cast<T*>(ptr.get()));
966}
967
975template <typename T, typename U>
977 return shared_ptr<T>(ptr, const_cast<T*>(ptr.get()));
978}
979
987template <typename T, typename U>
989 return shared_ptr<T>(ptr, reinterpret_cast<T*>(ptr.get()));
990}
991
999template <typename T, typename U>
1001 T* tmp = dynamic_cast<T*>(ptr.get());
1002 if (tmp != nullptr) {
1003 return shared_ptr<T>(ptr, tmp);
1004 }
1005 return nullptr;
1006}
1007 // SharedPointer
1009
1014
1019template <typename T>
1020struct hash<shared_ptr<T>> {
1021 NEFORCE_CONSTEXPR20 size_t operator()(const shared_ptr<T>& ptr) const
1022 noexcept(noexcept(_NEFORCE declval<_NEFORCE hash<T*>>()(_NEFORCE declval<T*>()))) {
1023 return hash<T*>()(ptr.get());
1024 }
1025};
1026 // HashPrimary
1028
1030NEFORCE_BEGIN_INNER__
1031
1032template <typename T>
1033class smart_pointer_atomic {
1034public:
1035 using value_type = T;
1036
1037private:
1038 struct atomic_counter {
1039 public:
1040 using count_type = inner::__smart_ptr_counter;
1041
1042 private:
1043 mutable atomic_base<uintptr_t> value_{0};
1044
1045 static constexpr uintptr_t lock_bit{1};
1046
1047 static void dereference(count_type* counter, true_type /*unused*/) noexcept { counter->decref_strong(); }
1048
1049 static void dereference(count_type* counter, false_type /*unused*/) noexcept { counter->decref_weak(); }
1050
1051 public:
1052 constexpr atomic_counter() noexcept = default;
1053
1054 explicit atomic_counter(count_type* counter) noexcept :
1055 value_(reinterpret_cast<uintptr_t>(counter)) {
1056 counter = nullptr;
1057 }
1058
1059 ~atomic_counter() {
1060 auto value = value_.load(memory_order_relaxed);
1061 NEFORCE_CONSTEXPR_ASSERT(!(value & lock_bit));
1062 if (auto* counter = reinterpret_cast<count_type*>(value)) {
1063 this->dereference(counter, is_shared_ptr<T>());
1064 }
1065 }
1066
1067 atomic_counter(const atomic_counter&) = delete;
1068 atomic_counter& operator=(const atomic_counter&) = delete;
1069
1070 count_type* lock(memory_order mo) const noexcept {
1071 if (mo != memory_order_seq_cst) {
1073 }
1074 auto cur = value_.load(memory_order_relaxed);
1075 while ((cur & lock_bit) != 0U) {
1076 this_thread::relax();
1077 cur = value_.load(memory_order_relaxed);
1078 }
1079
1080 while (!value_.compare_exchange_strong(cur, cur | lock_bit, mo, memory_order_relaxed)) {
1081 this_thread::relax();
1082 cur = cur & ~lock_bit;
1083 }
1084 return reinterpret_cast<count_type*>(cur);
1085 }
1086
1087 void unlock(memory_order mo) const noexcept { value_.fetch_sub(1, mo); }
1088
1089 count_type* swap_unlock(count_type* counter, memory_order mo) noexcept {
1090 if (mo != memory_order_seq_cst) {
1092 }
1093 auto addr = reinterpret_cast<uintptr_t>(counter);
1094 addr = value_.exchange(addr, mo);
1095 return reinterpret_cast<count_type*>(addr & ~lock_bit);
1096 }
1097
1098 void wait_unlock(memory_order mo) const noexcept {
1099 const auto old_value = value_.load(memory_order_relaxed);
1100 const auto unlocked = old_value & ~lock_bit;
1101 value_.fetch_sub(1, memory_order_release);
1102 if (value_.load(memory_order_acquire) == unlocked) {
1103 value_.wait(unlocked, mo);
1104 }
1105 }
1106
1107 void notify_one() noexcept { value_.notify_one(); }
1108
1109 void notify_all() noexcept { value_.notify_all(); }
1110 };
1111
1112 typename T::element_type* ptr_ = nullptr;
1113 atomic_counter refcount_;
1114
1115 friend struct atomic<T>;
1116
1117private:
1118 static typename atomic_counter::count_type* incref(typename atomic_counter::count_type* counter,
1119 true_type /*unused*/) {
1120 if (counter) {
1121 counter->incref_strong();
1122 }
1123 return counter;
1124 }
1125
1126 static typename atomic_counter::count_type* incref(typename atomic_counter::count_type* counter,
1127 false_type /*unused*/) {
1128 if (counter) {
1129 counter->incref_weak();
1130 }
1131 return counter;
1132 }
1133
1134public:
1135 constexpr smart_pointer_atomic() noexcept = default;
1136
1137 explicit smart_pointer_atomic(value_type value) noexcept :
1138 ptr_(value.ptr_),
1139 refcount_(value.owner_) {
1140 value.owner_ = nullptr;
1141 value.ptr_ = nullptr;
1142 }
1143
1144 ~smart_pointer_atomic() = default;
1145
1146 smart_pointer_atomic(const smart_pointer_atomic&) = delete;
1147 void operator=(const smart_pointer_atomic&) = delete;
1148
1149 value_type load(memory_order mo) const noexcept {
1150 NEFORCE_CONSTEXPR_ASSERT(mo != memory_order_release && mo != memory_order_acq_rel);
1151 if (mo != memory_order_seq_cst) {
1153 }
1154
1155 value_type value;
1156 auto counter = refcount_.lock(mo);
1157 value.ptr_ = ptr_;
1158 value.owner_ = this->incref(counter, is_shared_ptr<T>());
1159 refcount_.unlock(memory_order_relaxed);
1160 return value;
1161 }
1162
1163 void swap(value_type& value, memory_order mo) noexcept {
1164 refcount_.lock(memory_order_acquire);
1165 _NEFORCE swap(ptr_, value.ptr_);
1166 auto* old_owner = refcount_.swap_unlock(value.owner_, mo);
1167 value.owner_ = old_owner;
1168 }
1169
1170 bool compare_exchange_strong(value_type& expected, value_type desired, memory_order mo1,
1171 memory_order mo2) noexcept {
1172 bool result = true;
1173 auto* counter = refcount_.lock(memory_order_acquire);
1174 if (ptr_ == expected.ptr_ && counter == expected.owner_) {
1175 ptr_ = desired.ptr_;
1176 auto* old_owner = refcount_.swap_unlock(desired.owner_, mo1);
1177 desired.owner_ = old_owner;
1178 } else {
1179 auto* new_counter = this->incref(counter, is_shared_ptr<T>());
1180 refcount_.unlock(mo2);
1181 expected.ptr_ = ptr_;
1182 expected.owner_ = new_counter;
1183 result = false;
1184 }
1185 return result;
1186 }
1187
1188 void wait(value_type mold, memory_order mo) const noexcept {
1189 auto* counter = refcount_.lock(memory_order_acquire);
1190 if (ptr_ == mold.ptr_ && counter == mold.owner_) {
1191 refcount_.wait_unlock(mo);
1192 } else {
1193 refcount_.unlock(memory_order_relaxed);
1194 }
1195 }
1196
1197 void notify_one() noexcept { refcount_.notify_one(); }
1198
1199 void notify_all() noexcept { refcount_.notify_all(); }
1200};
1201
1202NEFORCE_END_INNER__
1204
1210
1217template <typename T>
1218struct atomic<shared_ptr<T>> {
1219public:
1220 using value_type = shared_ptr<T>;
1221
1222 static constexpr bool is_always_lock_free = false;
1223
1224private:
1225 inner::smart_pointer_atomic<value_type> atomic_;
1226
1227public:
1232 NEFORCE_NODISCARD bool is_lock_free() const noexcept { return false; }
1233
1237 constexpr atomic(nullptr_t = nullptr) noexcept {}
1238
1243 atomic(value_type value) noexcept :
1244 atomic_(move(value)) {}
1245
1246 atomic(const atomic&) = delete;
1247 void operator=(const atomic&) = delete;
1248
1254 value_type load(memory_order mo = memory_order_seq_cst) const noexcept { return atomic_.load(mo); }
1255
1259 operator value_type() const noexcept { return atomic_.load(memory_order_seq_cst); }
1260
1266 void store(value_type desired, memory_order mo = memory_order_seq_cst) noexcept { atomic_.swap(desired, mo); }
1267
1271 void operator=(value_type desired) noexcept { atomic_.swap(desired, memory_order_seq_cst); }
1272
1276 void operator=(nullptr_t) noexcept { store(nullptr); }
1277
1284 value_type exchange(value_type desired, memory_order mo = memory_order_seq_cst) noexcept {
1285 atomic_.swap(desired, mo);
1286 return desired;
1287 }
1288
1292 bool compare_exchange_strong(value_type& expected, value_type desired, memory_order mo, memory_order mo2) noexcept {
1293 return atomic_.compare_exchange_strong(expected, desired, mo, mo2);
1294 }
1295
1299 bool compare_exchange_strong(value_type& expected, value_type desired,
1300 memory_order mo = memory_order_seq_cst) noexcept {
1301 return compare_exchange_strong(expected, move(desired), mo, cmpexch_failure_order(mo));
1302 }
1303
1307 bool compare_exchange_weak(value_type& expected, value_type desired, memory_order mo, memory_order mo2) noexcept {
1308 return compare_exchange_strong(expected, move(desired), mo, mo2);
1309 }
1310
1314 bool compare_exchange_weak(value_type& expected, value_type desired,
1315 memory_order mo = memory_order_seq_cst) noexcept {
1316 return compare_exchange_strong(expected, move(desired), mo);
1317 }
1318
1322 void wait(value_type mold, memory_order mo = memory_order_seq_cst) const noexcept { atomic_.wait(move(mold), mo); }
1323
1327 void notify_one() noexcept { atomic_.notify_one(); }
1328
1332 void notify_all() noexcept { atomic_.notify_all(); }
1333};
1334 // AtomicOperations
1336
1337NEFORCE_END_NAMESPACE__
1338#endif // NEFORCE_CORE_MEMORY_SHARED_PTR_HPP__
比较算法
分配器特性
原子类型完整实现
add_lvalue_reference_t< T > operator[](size_t idx)
数组下标运算符
共享智能指针类模板
void reset(U *ptr)
重置共享指针并管理新对象
T * operator->() const noexcept
指针解引用运算符
shared_ptr & operator=(const shared_ptr &other) noexcept
拷贝赋值运算符
long use_count() const noexcept
获取引用计数
void swap(shared_ptr &other) noexcept
交换两个共享指针
shared_ptr & operator=(const shared_ptr< U > &other) noexcept
类型转换拷贝赋值运算符
shared_ptr & operator=(shared_ptr &&other) noexcept
移动赋值运算符
bool owner_equal(const shared_ptr< U > &rhs) const noexcept
检查所有权是否相等
shared_ptr(shared_ptr &&other) noexcept
移动构造函数
~shared_ptr() noexcept
析构函数
shared_ptr(const shared_ptr &other) noexcept
拷贝构造函数
shared_ptr(U *ptr, Deleter &&deleter)
从原始指针和自定义删除器构造函数
shared_ptr(shared_ptr< U > &&other) noexcept
类型转换移动构造函数
shared_ptr(shared_ptr< U > &&other, T *ptr) noexcept
移动别名构造函数
T * get() const noexcept
获取原始指针
shared_ptr(const shared_ptr< U > &other) noexcept
类型转换拷贝构造函数
bool owner_before(const shared_ptr< U > &rhs) const noexcept
比较所有权顺序
shared_ptr & operator=(shared_ptr< U > &&other) noexcept
类型转换移动赋值运算符
add_lvalue_reference_t< T > operator*() const noexcept
解引用运算符
void reset(U *ptr, Deleter deleter)
带自定义删除器重置共享指针并管理新对象
bool owner_equal(const weak_ptr< U > &rhs) const noexcept
与弱指针检查所有权是否相等
shared_ptr(nullptr_t np=nullptr) noexcept
默认构造函数
shared_ptr(U *ptr)
从原始指针构造函数
bool owner_before(const weak_ptr< U > &rhs) const noexcept
与弱指针比较所有权顺序
shared_ptr(unique_ptr< U, Deleter > &&unique)
独享智能指针构造函数
shared_ptr(const shared_ptr< U > &other, T *ptr) noexcept
从共享指针和别名指针别名构造函数
独占智能指针
弱智能指针类模板
异常处理框架
typename add_reference< T >::lvalue add_lvalue_reference_t
add_lvalue_reference的便捷别名
constexpr T * addressof(T &x) noexcept
获取对象的地址
constexpr T && forward(remove_reference_t< T > &x) noexcept
完美转发左值
constexpr bool is_base_of_v
is_base_of的便捷变量模板
constexpr const T & max(const T &a, const T &b, Compare comp) noexcept(noexcept(comp(a, b)))
返回两个值中的较大者
unsigned char byte_t
字节类型,定义为无符号字符
unsigned long uint64_t
64位无符号整数类型
decltype(nullptr) nullptr_t
空指针类型
void unreachable() noexcept
标记不可达代码路径
#define NEFORCE_CONSTEXPR_ASSERT(COND)
编译时常量断言
add_rvalue_reference_t< T > declval() noexcept
获取类型的右值引用,仅用于非求值上下文
bool operator!=(const function< Res(Args...)> &f, nullptr_t np) noexcept
不等于空指针比较
bool operator==(const function< Res(Args...)> &f, nullptr_t np) noexcept
等于空指针比较
constexpr T * construct(T *ptr, Args &&... args) noexcept(is_nothrow_constructible_v< T, Args... >)
在指定内存位置构造对象
constexpr auto memory_order_release
释放内存顺序常量
constexpr auto memory_order_seq_cst
顺序一致性内存顺序常量
constexpr memory_order cmpexch_failure_order(const memory_order mo) noexcept
获取原子比较交换操作失败时的内存顺序
constexpr auto memory_order_acquire
获取内存顺序常量
memory_order
内存顺序
@ release
释放操作,确保前面的读写不会被重排到后面
uint64_t uintptr_t
可容纳指针的无符号整数类型
typename remove_extent< T >::type remove_extent_t
remove_extent的便捷别名
shared_ptr< T > dynamic_pointer_cast(const shared_ptr< U > &ptr)
动态类型转换
shared_ptr< T > reinterpret_pointer_cast(const shared_ptr< U > &ptr)
重解释类型转换
shared_ptr< T > static_pointer_cast(const shared_ptr< U > &ptr)
静态类型转换
shared_ptr< T > const_pointer_cast(const shared_ptr< U > &ptr)
CV类型转换
enable_if_t<!is_array_v< T > &&is_constructible_v< T, Args... >, shared_ptr< T > > allocate_shared(Alloc &alloc, Args &&... args)
使用分配器创建共享指针
enable_if_t<!is_unbounded_array_v< T > &&is_constructible_v< T, Args... >, shared_ptr< T > > make_shared(Args &&... args)
融合分配创建共享指针
constexpr Iterator2 move(Iterator1 first, Iterator1 last, Iterator2 result) noexcept(noexcept(inner::__move_aux(first, last, result)))
移动范围元素
constexpr decltype(auto) size(const Container &cont) noexcept(noexcept(cont.size()))
获取容器的大小
constexpr bool is_constructible_v
is_constructible的便捷变量模板
constexpr bool is_nothrow_destructible_v
is_nothrow_destructible的便捷变量模板
typename enable_if< Test, T >::type enable_if_t
enable_if的便捷别名
bool_constant< false > false_type
表示false的类型
bool_constant< true > true_type
表示true的类型
void swap(unique_ptr< T, Deleter > &lhs, unique_ptr< T, Deleter > &rhs) noexcept
交换两个unique_ptr
static constexpr void construct(Alloc &alloc, T *ptr, Args &&... args) noexcept(noexcept(allocator_traits::__construct_aux(alloc, ptr, _NEFORCE forward< Args >(args)...)))
在已分配内存上构造对象
static constexpr void deallocate(Alloc &alloc, pointer ptr, size_type n)
释放内存
static constexpr void destroy(Alloc &alloc, T *ptr) noexcept(noexcept(allocator_traits::__destroy_aux(alloc, ptr, 0)))
销毁对象
static constexpr pointer allocate(Alloc &alloc, size_type n)
分配内存
value_type exchange(value_type desired, memory_order mo=memory_order_seq_cst) noexcept
交换操作
void operator=(value_type desired) noexcept
赋值操作符
value_type load(memory_order mo=memory_order_seq_cst) const noexcept
原子加载
void operator=(nullptr_t) noexcept
赋空值操作符
void wait(value_type mold, memory_order mo=memory_order_seq_cst) const noexcept
等待值改变
atomic(value_type value) noexcept
从shared_ptr构造
bool compare_exchange_strong(value_type &expected, value_type desired, memory_order mo=memory_order_seq_cst) noexcept
简化比较交换强版本
bool compare_exchange_weak(value_type &expected, value_type desired, memory_order mo=memory_order_seq_cst) noexcept
简化比较交换弱版本
void store(value_type desired, memory_order mo=memory_order_seq_cst) noexcept
原子存储
bool compare_exchange_strong(value_type &expected, value_type desired, memory_order mo, memory_order mo2) noexcept
比较交换强版本
constexpr atomic(nullptr_t=nullptr) noexcept
默认构造函数
bool compare_exchange_weak(value_type &expected, value_type desired, memory_order mo, memory_order mo2) noexcept
比较交换弱版本
void notify_one() noexcept
通知一个等待者
bool is_lock_free() const noexcept
检查是否无锁
void notify_all() noexcept
通知所有等待者
原子类型基础模板类
bool compare_exchange_strong(value_type &expected, value_type desired, const memory_order success, const memory_order failure) noexcept
强比较交换操作
void notify_one() noexcept
通知一个等待线程
void notify_all() noexcept
通知所有等待线程
value_type load(const memory_order mo=memory_order_seq_cst) const noexcept
原子加载操作
void wait(value_type old, const memory_order mo=memory_order_seq_cst) const noexcept
等待值改变
value_type fetch_sub(value_type value, const memory_order mo=memory_order_seq_cst) noexcept
原子获取并减去操作
value_type exchange(value_type value, const memory_order mo=memory_order_seq_cst) noexcept
原子交换操作
通用原子类型模板
shared_ptr< T > shared_from_this()
获取指向自身的共享指针
shared_ptr< const T > shared_from_this() const
获取指向自身的常量共享指针
enable_shared_from_this() noexcept=default
构造函数
哈希函数的主模板
类型特征:是否为shared_ptr
独占智能指针