vulkan-malloc 0.1.5

A general purpose device memory allocator for Vulkan
Documentation
use {SyncKey, SyncKeyId, SyncLock};
use std::cell::RefCell;
use std::sync::{Arc, Weak};

pub struct ListItem<T> {
    inner: SyncLock<RefCell<ListItemInner<T>>>,
}

impl<T> ListItem<T> {
    fn new(key_id: SyncKeyId, inner: ListItemInner<T>) -> Arc<ListItem<T>> {
        Arc::new(ListItem {
            inner: SyncLock::new(key_id, RefCell::new(inner)),
        })
    }

    fn set_prev(
        &self,
        key: &SyncKey,
        prev: Option<Weak<ListItem<T>>>,
    ) -> Option<Weak<ListItem<T>>> {
        let mut this = self.inner.get(key).unwrap().borrow_mut();
        ::std::mem::replace(&mut this.prev, prev)
    }

    pub fn prev(&self, key: &SyncKey) -> Option<Weak<ListItem<T>>> {
        self.inner.get(key).unwrap().borrow().prev.clone()
    }

    fn set_next(&self, key: &SyncKey, next: Option<Arc<ListItem<T>>>) -> Option<Arc<ListItem<T>>> {
        let mut this = self.inner.get(key).unwrap().borrow_mut();
        ::std::mem::replace(&mut this.next, next)
    }

    pub fn next(&self, key: &SyncKey) -> Option<Arc<ListItem<T>>> {
        self.inner.get(key).unwrap().borrow().next.clone()
    }

    pub fn with_value<F, V>(&self, key: &SyncKey, f: F) -> V
    where
        F: FnOnce(&T) -> V,
    {
        let this = self.inner.get(key).unwrap().borrow();
        f(&this.value)
    }

    pub fn with_value_mut<F, V>(&self, key: &SyncKey, f: F) -> V
    where
        F: FnOnce(&mut T) -> V,
    {
        let mut this = self.inner.get(key).unwrap().borrow_mut();
        f(&mut this.value)
    }

    pub fn is(&self, other: &ListItem<T>) -> bool {
        ::std::ptr::eq(self as *const _, other as *const _)
    }
}

struct ListItemInner<T> {
    prev: Option<Weak<ListItem<T>>>,
    next: Option<Arc<ListItem<T>>>,
    value: T,
}

pub struct List<T> {
    len: usize,
    head: SyncLock<RefCell<Option<Arc<ListItem<T>>>>>,
    tail: SyncLock<RefCell<Option<Arc<ListItem<T>>>>>,
}

impl<T> List<T> {
    pub fn new(key: &SyncKey) -> List<T> {
        List {
            len: 0,
            head: SyncLock::new(key.id(), RefCell::new(None)),
            tail: SyncLock::new(key.id(), RefCell::new(None)),
        }
    }

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

    pub fn push_back(&mut self, key: &SyncKey, value: T) -> Arc<ListItem<T>> {
        self.len += 1;
        let mut tail = self.tail.get(key).unwrap().borrow_mut();
        if let Some(tail_item) = tail.clone() {
            let item = ListItem::new(
                key.id(),
                ListItemInner {
                    prev: Some(Arc::downgrade(&tail_item)),
                    next: None,
                    value: value,
                },
            );
            tail_item.set_next(key, Some(item.clone()));
            *tail = Some(item.clone());
            item
        } else {
            let item = ListItem::new(
                key.id(),
                ListItemInner {
                    prev: None,
                    next: None,
                    value: value,
                },
            );
            *self.head.get(key).unwrap().borrow_mut() = Some(item.clone());
            *tail = Some(item.clone());
            item
        }
    }

    pub fn insert_after(
        &mut self,
        key: &SyncKey,
        item: Arc<ListItem<T>>,
        value: T,
    ) -> Arc<ListItem<T>> {
        self.len += 1;
        let current_next = item.next(key);
        let new_item = ListItem::new(
            key.id(),
            ListItemInner {
                prev: Some(Arc::downgrade(&item)),
                next: current_next.clone(),
                value: value,
            },
        );
        item.set_next(key, Some(new_item.clone()));
        if let Some(current_next) = current_next {
            current_next.set_prev(key, Some(Arc::downgrade(&new_item)));
        } else {
            *self.tail.get(key).unwrap().borrow_mut() = Some(new_item.clone());
        }
        new_item
    }

    pub fn insert_before(
        &mut self,
        key: &SyncKey,
        item: Arc<ListItem<T>>,
        value: T,
    ) -> Arc<ListItem<T>> {
        self.len += 1;
        let current_prev = item.prev(key);
        let new_item = ListItem::new(
            key.id(),
            ListItemInner {
                prev: current_prev.clone(),
                next: Some(item.clone()),
                value: value,
            },
        );
        item.set_prev(key, Some(Arc::downgrade(&new_item)));
        if let Some(current_prev) = current_prev {
            current_prev.upgrade().unwrap().set_next(key, Some(new_item.clone()));
        } else {
            *self.head.get(key).unwrap().borrow_mut() = Some(new_item.clone());
        }
        new_item
    }

    pub fn remove(&mut self, key: &SyncKey, item: &ListItem<T>) {
        self.len -= 1;
        let prev = item.prev(key);
        let next = item.next(key);
        let new_head = prev.is_none();
        let new_tail = next.is_none();
        if let Some(prev) = prev.clone() {
            let prev = prev.upgrade().unwrap();
            prev.set_next(key, next.clone());
        }
        if let Some(next) = next.clone() {
            next.set_prev(key, prev.clone());
        }
        if new_tail {
            *self.tail.get(key).unwrap().borrow_mut() = prev.map(|item| item.upgrade().unwrap());
        }
        if new_head {
            *self.head.get(key).unwrap().borrow_mut() = next;
        }
    }

    pub fn is_empty(&self, key: &SyncKey) -> bool {
        self.head.get(key).unwrap().borrow_mut().is_none()
    }

    pub fn iter<'a>(&self, key: &'a SyncKey) -> ListIter<'a, T> {
        ListIter {
            key: key,
            current: self.head.get(key).unwrap().borrow().clone(),
            tail: self.tail.get(key).unwrap().borrow().clone(),
        }
    }

    pub fn head(&self, key: &SyncKey) -> Option<Arc<ListItem<T>>> {
        self.head.get(key).unwrap().borrow().clone()
    }

    pub fn tail(&self, key: &SyncKey) -> Option<Arc<ListItem<T>>> {
        self.tail.get(key).unwrap().borrow().clone()
    }
}

pub struct ListIter<'a, T> {
    key: &'a SyncKey,
    current: Option<Arc<ListItem<T>>>,
    tail: Option<Arc<ListItem<T>>>,
}

impl<'a, T> Iterator for ListIter<'a, T>
where
    T: 'a,
{
    type Item = Arc<ListItem<T>>;

    fn next(&mut self) -> Option<Arc<ListItem<T>>> {
        let tail = if let Some(tail) = self.tail.as_ref() {
            tail
        } else {
            return None;
        };
        if let Some(item) = self.current.take() {
            if item.is(&*tail) {
                self.current = None;
            } else {
                self.current = item.next(self.key);
            }
            Some(item)
        } else {
            None
        }
    }
}