#![allow(dead_code)]
use std::sync::atomic::{AtomicUsize, Ordering};
use std::sync::{Mutex};
use std::ops::{Deref, DerefMut};
use std::cell::UnsafeCell;
use std::{fmt, ptr, cmp};
pub struct AVecReadGuard<'a, T: 'a> {
owner : &'a AVec<T>,
size : usize,
}
impl<'a, T> AVecReadGuard<'a, T> {
fn new(owner: &'a AVec<T>, size: usize) -> AVecReadGuard<'a, T> {
AVecReadGuard {
owner : &owner,
size : size,
}
}
}
impl<'a, T> Deref for AVecReadGuard<'a, T> {
type Target = [T];
fn deref(self: &Self) -> &[T] {
let data = self.owner.read();
&data[0..self.size]
}
}
impl<'a, T> Drop for AVecReadGuard<'a, T> {
fn drop(self: &mut Self) {
self.owner.end_read();
}
}
pub struct AVecMapGuard<'a, T: 'a> {
owner : &'a AVec<T>,
start : usize,
size : usize,
}
impl<'a, T> AVecMapGuard<'a, T> {
fn new(owner: &'a AVec<T>, start: usize, size: usize) -> AVecMapGuard<'a, T> {
AVecMapGuard {
owner : &owner,
start : start,
size : size,
}
}
pub fn mapped_range(self: &Self) -> (usize, usize) {
(self.start, self.start + self.size)
}
pub fn len(self: &Self) -> usize {
self.size
}
pub fn set(self: &Self, index: usize, value: T) -> &Self {
if index < self.size {
self.owner.write(self.start + index, value);
} else {
panic!("index out of bounds");
}
self
}
}
impl<'a, T> Drop for AVecMapGuard<'a, T> {
fn drop(&mut self) {
self.owner.end_write();
}
}
pub struct AVec<T> {
data: UnsafeCell<Vec<T>>,
insert: AtomicUsize,
readers: AtomicUsize,
writers: AtomicUsize,
initialized: UnsafeCell<usize>,
grow: Mutex<usize>,
}
unsafe impl<T> Sync for AVec<T> { }
unsafe impl<T> Send for AVec<T> { }
impl<'a, T> Drop for AVec<T> {
fn drop(&mut self) {
self.shrink_to_initialized();
}
}
impl<T> AVec<T> {
pub fn new(initial_capacity: usize) -> AVec<T> {
let instance = AVec::<T> {
data : UnsafeCell::new(Vec::new()),
insert : AtomicUsize::new(0),
readers : AtomicUsize::new(0),
writers : AtomicUsize::new(0),
initialized : UnsafeCell::new(0),
grow : Mutex::new(initial_capacity),
};
instance.resize(initial_capacity);
instance
}
pub fn push(self: &Self, value: T) -> usize {
self.begin_write();
let insert_pos = self.insert.fetch_add(1, Ordering::Relaxed);
while insert_pos >= self.capacity() {
self.grow(insert_pos + 1);
}
self.write(insert_pos, value);
self.end_write();
insert_pos
}
pub fn map<'a>(&'a self, size: usize) -> AVecMapGuard<'a, T> {
self.begin_write();
let insert_pos = self.insert.fetch_add(size, Ordering::Relaxed);
let required_capacity = insert_pos + size;
while required_capacity > self.capacity() {
self.grow(required_capacity);
}
AVecMapGuard::new(&self, insert_pos, size)
}
pub fn len(self: &Self) -> usize {
self.insert.load(Ordering::Relaxed)
}
pub fn grow(self: &Self, required_capacity: usize) {
let mut guard = self.grow.lock().unwrap();
let capacity = self.capacity();
if required_capacity > capacity {
let new_capacity = if required_capacity > capacity * 2 {
self.resize(required_capacity)
} else {
self.resize(capacity * 2)
};
*guard.deref_mut() = new_capacity; }
}
pub fn clear(self: &Self) {
if self.readers.fetch_add(1, Ordering::SeqCst) > 0 {
panic!("Attempt read+write with concurrent readers");
}
if self.writers.fetch_add(1, Ordering::SeqCst) > 0 {
panic!("Attempt read+write with concurrent writers");
}
let current_max = self.insert.swap(0, Ordering::SeqCst);
self.update_initialized(current_max);
self.readers.fetch_sub(1, Ordering::SeqCst);
self.writers.fetch_sub(1, Ordering::SeqCst);
}
pub fn get<'a>(&'a self) -> AVecReadGuard<'a, T> {
self.begin_read();
let size = self.insert.load(Ordering::SeqCst);
AVecReadGuard::new(&self, size)
}
pub fn capacity(self: &Self) -> usize {
self.read().capacity()
}
fn shrink_to_initialized(self: &Self) {
let mut guard = self.grow.lock().unwrap();
let num_initialized = self.initialized();
self.resize(num_initialized);
*guard.deref_mut() = num_initialized;
}
fn resize(self: &Self, new_size: usize) -> usize {
unsafe {
let mut data = &mut *self.data.get();
let capacity = data.capacity();
if new_size > capacity {
data.reserve(new_size - capacity);
data.set_len(new_size);
} else if new_size < capacity {
if new_size < self.initialized() {
panic!("Attempted to reduce size below initialized number of elements.")
}
data.set_len(new_size);
data.shrink_to_fit();
}
data.capacity()
}
}
fn update_initialized(self: &Self, num_initialized: usize) {
unsafe {
let current = *self.initialized.get();
if num_initialized > current {
*self.initialized.get() = num_initialized;
}
}
}
fn initialized(self: &Self) -> usize {
unsafe { cmp::max(*self.initialized.get(), self.len()) }
}
fn write(self: &Self, insert_pos: usize, value: T) {
unsafe {
let mut data = &mut *self.data.get();
if insert_pos < *self.initialized.get() {
ptr::drop_in_place(&mut data[insert_pos]);
}
ptr::write(&mut data[insert_pos], value);
}
}
fn read(self: &Self) -> &Vec<T> {
unsafe { &*self.data.get() }
}
fn begin_read(self: &Self) {
self.readers.fetch_add(1, Ordering::SeqCst);
if self.writers.load(Ordering::SeqCst) > 0 {
panic!("Attempt to read during concurrent write");
}
}
fn end_read(self: &Self) {
self.readers.fetch_sub(1, Ordering::SeqCst);
}
fn begin_write(self: &Self) {
self.writers.fetch_add(1, Ordering::SeqCst);
if self.readers.load(Ordering::SeqCst) > 0 {
panic!("Attempt to write during concurrent reads");
}
}
fn end_write(self: &Self) {
self.writers.fetch_sub(1, Ordering::SeqCst);
}
}
impl<T> fmt::Debug for AVec<T> where T: fmt::Debug {
fn fmt(self: &Self, f: &mut fmt::Formatter) -> fmt::Result {
let data = self.get();
write!(f, "AVec{:?}", data.deref())
}
}