Skip to content

Commit

Permalink
Add type for RetiredPtrs (use Vec instead of LinkedList)
Browse files Browse the repository at this point in the history
  • Loading branch information
skogseth committed Sep 26, 2023
1 parent dff8df9 commit 99d42bb
Show file tree
Hide file tree
Showing 4 changed files with 70 additions and 55 deletions.
22 changes: 8 additions & 14 deletions src/cell.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,7 @@ use std::marker::PhantomData;
use std::ptr::NonNull;
use std::sync::Mutex;

use crate::core::{HzrdCore, HzrdPtr, HzrdPtrs, RefHandle};
use crate::linked_list::LinkedList;
use crate::utils::RetiredPtr;
use crate::core::{HzrdCore, HzrdPtr, HzrdPtrs, RefHandle, RetiredPtr, RetiredPtrs};
use crate::utils::{allocate, free};

/**
Expand Down Expand Up @@ -82,13 +80,13 @@ impl<T> HzrdCell<T> {
let old_ptr = inner.core.swap(value);

let mut retired = inner.retired.lock().unwrap();
retired.push_back(RetiredPtr::new(old_ptr));
retired.add(RetiredPtr::new(old_ptr));

let Ok(hzrd_ptrs) = inner.hzrd_ptrs.try_lock() else {
return;
};

crate::utils::reclaim(&mut retired, &hzrd_ptrs);
retired.reclaim(&hzrd_ptrs);
}

/**
Expand Down Expand Up @@ -199,11 +197,7 @@ impl<T> HzrdCell<T> {
pub fn just_set(&self, value: T) {
let inner = self.inner();
let old_ptr = inner.core.swap(value);
inner
.retired
.lock()
.unwrap()
.push_back(RetiredPtr::new(old_ptr));
inner.retired.lock().unwrap().add(RetiredPtr::new(old_ptr));
}

/// Reclaim available memory
Expand Down Expand Up @@ -288,15 +282,15 @@ impl<T> Drop for HzrdCell<T> {
struct HzrdCellInner<T> {
core: HzrdCore<T>,
hzrd_ptrs: Mutex<HzrdPtrs>,
retired: Mutex<LinkedList<RetiredPtr<T>>>,
retired: Mutex<RetiredPtrs<T>>,
}

impl<T> HzrdCellInner<T> {
pub fn new(boxed: Box<T>) -> Self {
Self {
core: HzrdCore::new(boxed),
hzrd_ptrs: Mutex::new(HzrdPtrs::new()),
retired: Mutex::new(LinkedList::new()),
retired: Mutex::new(RetiredPtrs::new()),
}
}

Expand All @@ -320,7 +314,7 @@ impl<T> HzrdCellInner<T> {
// Wait for access to the hazard pointers
let hzrd_ptrs = self.hzrd_ptrs.lock().unwrap();

crate::utils::reclaim(&mut retired, &hzrd_ptrs);
retired.reclaim(&hzrd_ptrs);
}

/// Try to reclaim memory, but don't wait for the shared lock to do so
Expand All @@ -341,7 +335,7 @@ impl<T> HzrdCellInner<T> {
return;
};

crate::utils::reclaim(&mut retired, &hzrd_ptrs);
retired.reclaim(&hzrd_ptrs);
}
}

Expand Down
57 changes: 57 additions & 0 deletions src/core.rs
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,63 @@ impl<T> Drop for HzrdCore<T> {
}
}

pub struct RetiredPtr<T>(NonNull<T>);

impl<T> RetiredPtr<T> {
pub fn new(ptr: NonNull<T>) -> Self {
RetiredPtr(ptr)
}

pub fn as_ptr(&self) -> *mut T {
self.0.as_ptr()
}
}

impl<T> Drop for RetiredPtr<T> {
fn drop(&mut self) {
// SAFETY: No reference to this when dropped
unsafe { crate::utils::free(self.0) };
}
}

pub struct RetiredPtrs<T>(Vec<RetiredPtr<T>>);

impl<T> RetiredPtrs<T> {
pub fn new() -> Self {
Self(Vec::new())
}

pub fn add(&mut self, val: RetiredPtr<T>) {
self.0.push(val);
}

pub fn reclaim(&mut self, hzrd_ptrs: &HzrdPtrs) {
let mut still_active = Vec::new();
while let Some(retired_ptr) = self.0.pop() {
if hzrd_ptrs.contains(retired_ptr.as_ptr() as usize) {
still_active.push(retired_ptr);
continue;
}
}

self.0 = still_active;
}

pub fn is_empty(&self) -> bool {
self.0.is_empty()
}

pub fn len(&self) -> usize {
self.0.len()
}
}

impl<T> Default for RetiredPtrs<T> {
fn default() -> Self {
Self::new()
}
}

#[cfg(test)]
mod tests {
use super::*;
Expand Down
12 changes: 5 additions & 7 deletions src/pair.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,7 @@ std::thread::scope(|s| {

use std::ptr::NonNull;

use crate::core::{HzrdCore, HzrdPtr, HzrdPtrs};
use crate::linked_list::LinkedList;
use crate::utils::RetiredPtr;
use crate::core::{HzrdCore, HzrdPtr, HzrdPtrs, RetiredPtr, RetiredPtrs};
use crate::RefHandle;

/**
Expand All @@ -53,7 +51,7 @@ pub struct HzrdReader<'writer, T> {

struct Ptrs<T> {
hzrd: HzrdPtrs,
retired: LinkedList<RetiredPtr<T>>,
retired: RetiredPtrs<T>,
}

impl<T> HzrdWriter<T> {
Expand Down Expand Up @@ -110,16 +108,16 @@ impl<T> HzrdWriter<T> {
// - The reference is not held alive beyond this function
let ptrs = unsafe { &mut *self.ptrs.as_ptr() };

ptrs.retired.push_back(RetiredPtr::new(old_ptr));
crate::utils::reclaim(&mut ptrs.retired, &ptrs.hzrd);
ptrs.retired.add(RetiredPtr::new(old_ptr));
ptrs.retired.reclaim(&ptrs.hzrd);
}
}

impl<T> From<Box<T>> for HzrdWriter<T> {
fn from(boxed: Box<T>) -> Self {
let ptrs = Ptrs {
hzrd: HzrdPtrs::new(),
retired: LinkedList::new(),
retired: RetiredPtrs::new(),
};

Self {
Expand Down
34 changes: 0 additions & 34 deletions src/utils.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
use std::ptr::NonNull;

use crate::core::HzrdPtrs;
use crate::linked_list::LinkedList;

/// Place object on the heap (will leak)
pub fn allocate<T>(object: T) -> NonNull<T> {
let raw = Box::into_raw(Box::new(object));
Expand All @@ -15,34 +12,3 @@ pub fn allocate<T>(object: T) -> NonNull<T> {
pub unsafe fn free<T>(non_null_ptr: NonNull<T>) {
let _ = Box::from_raw(non_null_ptr.as_ptr());
}

pub struct RetiredPtr<T>(NonNull<T>);

impl<T> RetiredPtr<T> {
pub fn new(ptr: NonNull<T>) -> Self {
RetiredPtr(ptr)
}

pub fn as_ptr(&self) -> *mut T {
self.0.as_ptr()
}
}

impl<T> Drop for RetiredPtr<T> {
fn drop(&mut self) {
// SAFETY: No reference to this when dropped
unsafe { free(self.0) };
}
}

pub fn reclaim<T>(retired_ptrs: &mut LinkedList<RetiredPtr<T>>, hzrd_ptrs: &HzrdPtrs) {
let mut still_active = LinkedList::new();
while let Some(retired_ptr) = retired_ptrs.pop_front() {
if hzrd_ptrs.contains(retired_ptr.as_ptr() as usize) {
still_active.push_back(retired_ptr);
continue;
}
}

*retired_ptrs = still_active;
}

0 comments on commit 99d42bb

Please sign in to comment.