1#ifndef NEFORCE_CORE_ASYNC_HAZARD_PTR_HPP__
2#define NEFORCE_CORE_ASYNC_HAZARD_PTR_HPP__
16NEFORCE_BEGIN_NAMESPACE__
40struct hazard_pointer_record {
52 bool expected =
false;
90 NEFORCE_NODISCARD
virtual void*
get_ptr()
const = 0;
101template <
typename T,
typename Deleter = default_deleter<
void>>
114 deleter(_NEFORCE
move(d)) {}
121 NEFORCE_NODISCARD
void*
get_ptr()
const override {
return static_cast<void*
>(ptr); }
139 retire_list(retire_list&& other) noexcept :
142 other.head =
nullptr;
156 other.head =
nullptr;
183 while (
head !=
nullptr) {
199class hazard_pointer_domain {
208 static constexpr size_t RETIRE_THRESHOLD = 100;
218 while (current !=
nullptr) {
221 if (ptr !=
nullptr) {
237 void scan_and_reclaim() {
238 auto hazards = get_hazard_pointers();
241 auto& thread_list = get_thread_retire_list();
243 thread_list.head =
nullptr;
244 thread_list.count = 0;
247 size_t keep_count = 0;
250 while (current !=
nullptr) {
252 void* inner_ptr = current->
get_ptr();
255 current->
next = keep_head;
259 current->
next = destroy_head;
260 destroy_head = current;
265 while (destroy_head !=
nullptr) {
272 thread_list.head = keep_head;
273 thread_list.count = keep_count;
277 hazard_pointer_domain() =
default;
286 while (current !=
nullptr) {
304 while (current !=
nullptr) {
331 template <
typename T,
typename Deleter = default_deleter<T>>
332 void retire(T* ptr, Deleter deleter = Deleter()) {
338 get_thread_retire_list().add(obj);
340 if (get_thread_retire_list().
count >= RETIRE_THRESHOLD) {
355 static hazard_pointer_domain domain{};
367class hazard_pointer {
373 hazard_pointer() =
default;
383 record_ = domain_->acquire_record();
393 if (record_ !=
nullptr) {
399 record_(other.record_),
400 domain_(other.domain_) {
401 other.record_ =
nullptr;
402 other.domain_ =
nullptr;
405 hazard_pointer& operator=(hazard_pointer&& other)
noexcept {
411 if (record_ !=
nullptr) {
414 record_ = other.record_;
415 domain_ = other.domain_;
416 other.record_ =
nullptr;
417 other.domain_ =
nullptr;
422 hazard_pointer(
const hazard_pointer&) =
delete;
423 hazard_pointer& operator=(
const hazard_pointer&) =
delete;
433 template <
typename T>
441 record_->protect(ptr);
457 template <
typename T>
464 record_->protect(ptr);
481 if (record_ !=
nullptr) {
482 record_->protect(
nullptr);
490 void swap(hazard_pointer& other)
noexcept {
491 _NEFORCE
swap(record_, other.record_);
492 _NEFORCE
swap(domain_, other.domain_);
499 explicit operator bool() const noexcept {
return record_ !=
nullptr; }
520class hazard_pointer_holder {
526 hazard_pointer_holder() =
default;
541 ptr_ = hp_.protect(src);
549 T*
get() const noexcept {
return ptr_; }
567 explicit operator bool() const noexcept {
return ptr_ !=
nullptr; }
573 hp_.reset_protection();
582NEFORCE_END_NAMESPACE__
static hazard_pointer_domain & default_domain()
获取默认的险象指针域
void retire(T *ptr, Deleter deleter=Deleter())
退役一个对象
hazard_pointer_record * acquire_record()
获取一个可用的险象指针记录
~hazard_pointer_domain()
析构函数
T & operator*() const noexcept
解引用操作符
T * protect(const atomic< T * > &src)
保护原子指针
T * get() const noexcept
获取当前保护的指针
void reset() noexcept
重置持有的指针
T * operator->() const noexcept
箭头操作符
hazard_pointer_holder(hazard_pointer_domain &domain)
构造函数
virtual void * get_ptr() const =0
获取包装的内部指针
virtual void destroy()=0
销毁对象
hazard_pointer_obj_base * next
链表中的下一个对象
hazard_pointer_obj(T *p, Deleter d=Deleter())
构造函数
void destroy() override
销毁对象
void * get_ptr() const override
获取包装的内部指针
void swap(hazard_pointer &other) noexcept
交换两个险象指针
bool try_protect(T *&ptr, const atomic< T * > &src)
尝试保护一个原子指针
void reset_protection() noexcept
重置保护
T * protect(const atomic< T * > &src)
保护一个原子指针
hazard_pointer(hazard_pointer_domain &domain)
构造函数
constexpr void push_back(const T &value)
在末尾拷贝插入元素
constexpr T * addressof(T &x) noexcept
获取对象的地址
constexpr bool binary_search(Iterator first, Iterator last, const T &value)
在有序范围内进行二分查找
constexpr iter_difference_t< Iterator > count(Iterator first, Iterator last, const T &value)
统计范围内等于指定值的元素数量
hazard_pointer make_hazard_pointer(hazard_pointer_domain &domain=hazard_pointer_domain::default_domain())
创建险象指针的辅助函数
constexpr Iterator next(Iterator iter, iter_difference_t< Iterator > n=1)
获取迭代器的后一个位置
constexpr auto memory_order_release
释放内存顺序常量
constexpr auto memory_order_relaxed
宽松内存顺序常量
constexpr auto memory_order_acquire
获取内存顺序常量
constexpr Iterator2 move(Iterator1 first, Iterator1 last, Iterator2 result) noexcept(noexcept(inner::__move_aux(first, last, result)))
移动范围元素
void sort(Iterator first, Iterator last, Compare comp)
标准排序
void swap()=delete
删除无参数的swap重载
bool load(const memory_order mo=memory_order_seq_cst) const noexcept
原子加载操作
T load(const memory_order mo=memory_order_seq_cst) const noexcept
原子加载操作
void protect(void *ptr)
保护指定的指针
atomic< hazard_pointer_record * > next
链表中的下一个记录
atomic< void * > hazard_ptr
受保护的指针
bool try_acquire()
尝试获取记录的所有权
void * get_protected() const
获取当前保护的指针
atomic< bool > active
记录是否活跃
void add(hazard_pointer_obj_base *obj)
添加对象到退役列表
hazard_pointer_obj_base * head
链表头
retire_list & operator=(retire_list &&other) noexcept
移动赋值运算符