您好,登錄后才能下訂單哦!
這篇文章給大家介紹crossbeam-epoch中基于epoch的無鎖垃圾收集原理是什么,內容非常詳細,感興趣的小伙伴們可以參考借鑒,希望對大家能有所幫助。
crossbeam提供了一個基于epoch的“垃圾收集”(epoch based reclamation)庫。首先來簡單的說一下這一垃圾回收的原理。
pin
可以產生
Guard
,這將當前線程標識為活躍use crossbeam_epoch as epoch;
let guard = &epoch::pin();
defer_destroy
則將數據放入垃圾列表,等待2個epoch之后就可以被清理了pub unsafe fn defer_destroy<T>(&self, ptr: Shared<T>)
defer_destroy
的函數簽名中看到了
Shared<T>
,這是一個被Guard的生命周期
'g
所保護的指針類型,相當于
&'g T
。它保證了Guard存在期間數據的可訪問。Box<T>
,是一個不會被其他線程接觸到的量。Guard
的保護下從中讀出
Shared<T>
pub fn load(&self, ord: Ordering, &'g Guard) -> Shared<'g, T>
Owned<T>
或者
Shared<T>
(即
Pointer<T>
)存入pub fn store<P>(&self, new: P, ord: Ordering)where P: Pointer<T>,
pub fn compare_and_set<O, P>( &self, current: Shared<T>, new: P, ord: O, &'g Guard) -> Result<Shared<'g, T>, CompareAndSetError<'g, T, P>>where O: CompareAndSetOrdering, P: Pointer<T>,
use std::mem::ManuallyDrop;
use std::ptr;
use std::sync::atomic::Ordering::{Acquire, Relaxed, Release};
use crossbeam_epoch::{self as epoch, Atomic, Owned};
#[derive(Debug)]
pub struct TreiberStack<T> {
head: Atomic<Node<T>>,
}
#[derive(Debug)]
struct Node<T> {
data: ManuallyDrop<T>, // 告訴編譯器該變量不需要自動Drop
next: Atomic<Node<T>>,
}
impl<T> TreiberStack<T> {
pub fn new() -> TreiberStack<T> {
TreiberStack {
head: Atomic::null(),
}
}
pub fn push(&self, t: T) {
let mut n = Owned::new(Node {
data: ManuallyDrop::new(t),
next: Atomic::null(),
});
let guard = epoch::pin(); // 標記當前線程為活躍
loop {
let head = self.head.load(Relaxed, &guard);
n.next.store(head, Relaxed);
match self.head.compare_and_set(head, n, Release, &guard) { // CAS
Ok(_) => break,
Err(e) => n = e.new,
}
}
}
pub fn pop(&self) -> Option<T> {
let guard = epoch::pin(); // 標記當前線程為活躍
loop {
let head = self.head.load(Acquire, &guard);
match unsafe { head.as_ref() } {
Some(h) => {
let next = h.next.load(Relaxed, &guard);
if self
.head
.compare_and_set(head, next, Relaxed, &guard) // CAS
.is_ok()
{
unsafe {
guard.defer_destroy(head); // 將垃圾加入列表
return Some(ManuallyDrop::into_inner(ptr::read(&(*h).data))); // 返回節點中的數據
}
}
}
None => return None,
}
}
}
pub fn is_empty(&self) -> bool {
let guard = epoch::pin();
self.head.load(Acquire, &guard).is_null()
}
}
impl<T> Drop for TreiberStack<T> {
fn drop(&mut self) {
while self.pop().is_some() {}
}
}
關于crossbeam-epoch中基于epoch的無鎖垃圾收集原理是什么就分享到這里了,希望以上內容可以對大家有一定的幫助,可以學到更多知識。如果覺得文章不錯,可以把它分享出去讓更多的人看到。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。