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;
100template <
typename T,
typename Deleter = default_delete<
void>>
113 deleter(_NEFORCE
move(d)) {}
166class hazard_pointer_domain {
172 static constexpr size_t RETIRE_THRESHOLD = 100;
201 void scan_and_reclaim() {
202 auto hazards = get_hazard_pointers();
203 _NEFORCE
sort(hazards.begin(), hazards.end());
211 if (_NEFORCE
binary_search(hazards.begin(), hazards.end(), current)) {
212 new_list.
add(current);
221 tl_retire_list_ = _NEFORCE
move(new_list);
225 hazard_pointer_domain() =
default;
279 template <
typename T,
typename Deleter = default_delete<T>>
280 void retire(T* ptr, Deleter deleter = Deleter()) {
286 tl_retire_list_.add(obj);
288 if (tl_retire_list_.count >= RETIRE_THRESHOLD) {
303 static hazard_pointer_domain domain{};
315class hazard_pointer {
321 hazard_pointer() =
default;
331 record_ = domain_->acquire_record();
347 record_(other.record_),
348 domain_(other.domain_) {
349 other.record_ =
nullptr;
350 other.domain_ =
nullptr;
353 hazard_pointer& operator=(hazard_pointer&& other)
noexcept {
362 record_ = other.record_;
363 domain_ = other.domain_;
364 other.record_ =
nullptr;
365 other.domain_ =
nullptr;
370 hazard_pointer(
const hazard_pointer&) =
delete;
371 hazard_pointer& operator=(
const hazard_pointer&) =
delete;
381 template <
typename T>
389 record_->protect(ptr);
405 template <
typename T>
412 record_->protect(ptr);
430 record_->protect(
nullptr);
438 void swap(hazard_pointer& other)
noexcept {
439 _NEFORCE
swap(record_, other.record_);
440 _NEFORCE
swap(domain_, other.domain_);
447 explicit operator bool() const noexcept {
return record_ !=
nullptr; }
468class hazard_pointer_holder {
474 hazard_pointer_holder() =
default;
489 ptr_ = hp_.protect(src);
497 T*
get() const noexcept {
return ptr_; }
515 explicit operator bool() const noexcept {
return ptr_ !=
nullptr; }
521 hp_.reset_protection();
530NEFORCE_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 destroy()=0
销毁对象
hazard_pointer_obj_base * next
链表中的下一个对象
hazard_pointer_obj(T *p, Deleter d=Deleter())
构造函数
void destroy() 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)
构造函数
NEFORCE_CONSTEXPR20 void push_back(const T &value)
在末尾拷贝插入元素
NEFORCE_NODISCARD constexpr T * addressof(T &x) noexcept
获取对象的地址
constexpr bool binary_search(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)
获取迭代器的后一个位置
NEFORCE_INLINE17 constexpr auto memory_order_release
释放内存顺序常量
NEFORCE_INLINE17 constexpr auto memory_order_relaxed
宽松内存顺序常量
NEFORCE_INLINE17 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重载
void store(const bool value, const memory_order mo=memory_order_seq_cst) noexcept
原子存储操作
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 store(T value, const memory_order mo=memory_order_seq_cst) 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
链表头