use crate::convert::PFrom;
use crate::alloc::get_idx;
use crate::alloc::MemPool;
use crate::clone::PClone;
use crate::ptr::*;
use crate::stm::*;
use crate::*;
use std::alloc::Layout;
use std::cmp::Ordering;
use std::fmt::{Debug, Display, Formatter};
use std::marker::PhantomData;
use std::ops::Index;
use std::slice::SliceIndex;
use std::vec::Vec as StdVec;
use std::{mem, ptr, slice};
pub struct Vec<T: PSafe, A: MemPool> {
buf: Slice<T, A>,
len: usize,
has_log: u8,
marker: PhantomData<[T]>,
}
unsafe impl<T: PSafe, A: MemPool> PSafe for Vec<T, A> {}
impl<T, A: MemPool> !Send for Vec<T, A> {}
impl<T, A: MemPool> !Sync for Vec<T, A> {}
impl<T, A: MemPool> !VSafe for Vec<T, A> {}
impl<T: PSafe, A: MemPool> Vec<T, A> {
pub const fn new() -> Self {
Self::empty()
}
pub fn from_slice(x: &[T], journal: &Journal<A>) -> Self {
if x.len() == 0 {
Self::empty()
} else {
let buf = unsafe { A::new_slice(x, journal) };
let offset = unsafe { A::off_unchecked(buf) };
Self::from_off_len(offset, buf.len(), buf.len())
}
}
pub(crate) unsafe fn from_slice_nolog(x: &[T]) -> (Self, usize) {
if x.len() == 0 {
(Self::empty(), 0)
} else {
let (buf, off, _, z) = A::atomic_new_slice(x);
(Self::from_off_len(off, buf.len(), buf.len()), z)
}
}
pub fn with_capacity(cap: usize, j: &Journal<A>) -> Self {
if cap == 0 {
Self::empty()
} else {
let layout = Layout::array::<T>(cap).unwrap();
unsafe {
let buf = A::new_uninit_for_layout(layout.size(), j);
Self::from_off_len(A::off_unchecked(buf), cap, 0)
}
}
}
#[inline]
pub unsafe fn from_raw_parts(ptr: *mut T, length: usize, capacity: usize) -> Self {
let off = A::off_unchecked(ptr);
Self {
buf: Slice::<T,A>::from_off_cap(off, capacity),
len: length,
has_log: 0,
marker: PhantomData
}
}
pub const fn empty() -> Self {
Self::from_off_len(u64::MAX, 0, 0)
}
pub fn is_empty(&self) -> bool {
self.len == 0
}
#[inline]
pub fn split_off(&mut self, at: usize, j: &Journal<A>) -> Self {
assert!(at <= self.len(), "`at` out of bounds");
let other_len = self.len - at;
let mut other = Vec::with_capacity(other_len, j);
unsafe {
self.set_len(at);
other.set_len_volatile(other_len);
ptr::copy_nonoverlapping(
self.as_ptr().add(at),
other.to_slice_mut().as_mut_ptr(),
other.len(),
);
}
other
}
pub(crate) const fn from_off_len(offset: u64, capacity: usize, length: usize) -> Self {
Self {
buf: Slice::from_off_cap(offset, capacity),
len: length,
has_log: 0,
marker: PhantomData,
}
}
pub(crate) unsafe fn into_raw_parts(&self) -> (*mut T, usize, usize) {
(
A::get_mut_unchecked(self.buf.off()),
self.len,
self.buf.capacity(),
)
}
#[inline]
fn get(&self, i: usize) -> &T {
self.buf.get(i)
}
#[inline]
fn get_mut(&self, i: usize) -> &mut T {
self.buf.get_mut(i)
}
#[inline]
pub fn off(&self) -> u64 {
self.buf.off()
}
#[inline]
pub fn capacity(&self) -> usize {
self.buf.capacity()
}
#[inline]
pub unsafe fn set_len(&mut self, new_len: usize) {
debug_assert!(new_len <= self.buf.capacity());
self.len = new_len;
}
fn set_len_volatile(&mut self, new_len: usize) {
debug_assert!(new_len <= self.buf.capacity());
self.len = new_len;
}
#[inline]
pub fn len(&self) -> usize {
self.len
}
#[inline]
pub fn as_slice(&self) -> &[T] {
Self::to_slice(self.off(), self.len)
}
#[inline]
pub(crate) unsafe fn as_ptr(&self) -> *mut T {
if self.len == 0 {
std::ptr::null_mut()
} else {
A::get_mut_unchecked(self.off())
}
}
#[inline]
pub fn as_slice_mut(&mut self, j: &Journal<A>) -> &mut [T] {
let res = Self::__to_slice_mut(self.off(), self.len());
if self.has_log == 0 {
unsafe {
res.create_log(j, Notifier::NonAtomic(Ptr::from_ref(&self.has_log)));
}
}
self.to_slice_mut()
}
#[inline]
pub(crate) unsafe fn as_vec(&mut self) -> StdVec<T> {
StdVec::from_raw_parts(self.buf.as_mut_ptr(), self.len, self.buf.capacity())
}
#[inline]
fn to_slice<'a>(off: u64, len: usize) -> &'a [T] {
unsafe { A::deref_slice_unchecked(off, len) }
}
#[inline]
fn __to_slice_mut<'a>(off: u64, len: usize) -> &'a mut [T] {
unsafe { A::deref_slice_unchecked_mut(off, len) }
}
#[inline]
pub(crate) fn to_slice_mut(&mut self) -> &mut [T] {
Self::__to_slice_mut(self.off(), self.len())
}
pub fn extend_from_slice(&mut self, other: &[T], j: &Journal<A>) {
if other.len() != 0 {
unsafe {
let len = self.len;
let new_cap = self.capacity().max(len + other.len());
self.reserve(new_cap - self.capacity(), j);
let ptr = self.buf.as_mut_ptr();
ptr::copy(other.as_ptr(), ptr.add(len), other.len());
self.len += other.len();
}
}
}
#[inline]
pub fn shrink_to(&mut self, new_cap: usize, j: &Journal<A>) {
let cap = self.capacity();
eprintln!("shrink_to");
let new_cap = new_cap.max(self.len);
if get_idx(new_cap * mem::size_of::<T>()) != get_idx(cap * mem::size_of::<T>()) {
unsafe {
let buf = self.to_slice_mut();
let (rem, left) = buf.split_at_mut(buf.len().min(new_cap));
if !left.is_empty() {
ptr::drop_in_place(left);
}
if rem.is_empty() {
self.buf = Slice::null();
} else {
let new = A::new_slice(rem, j);
self.buf = Slice::from_off_cap(A::off_unchecked(new), new.len());
}
}
}
self.buf.set_cap(new_cap);
}
pub fn shrink_to_fit(&mut self, j: &Journal<A>) {
if self.capacity() != self.len {
self.shrink_to(self.len, j);
}
}
#[inline]
pub fn reserve(&mut self, additional: usize, j: &Journal<A>) {
if additional == 0 {
return;
}
let cap = self.buf.capacity();
let len = self.len;
let new_cap = cap.max(len + additional);
if get_idx(new_cap * mem::size_of::<T>()) == get_idx(len * mem::size_of::<T>()) {
self.buf.set_cap(new_cap);
} else {
unsafe {
let old = self.to_slice_mut();
let layout = Layout::array::<T>(new_cap).unwrap();
let new = A::new_uninit_for_layout(layout.size(), j).cast();
ptr::copy(old.as_ptr(), new, len);
A::free_slice(Self::__to_slice_mut(self.off(), self.capacity()));
self.buf = Slice::new(slice::from_raw_parts(new, new_cap));
}
}
}
pub fn truncate(&mut self, len: usize) {
unsafe {
if len > self.len {
return;
}
let s = &mut self.to_slice_mut()[len..];
ptr::drop_in_place(s);
}
self.len = len;
}
#[inline]
pub fn swap_remove(&mut self, index: usize) -> T {
unsafe {
let hole: *mut T = &mut self.to_slice_mut()[index];
let last = ptr::read(self.buf.get_unchecked(self.len - 1));
self.len -= 1;
ptr::replace(hole, last)
}
}
pub fn insert(&mut self, index: usize, element: T, j: &Journal<A>) {
let len = self.len();
assert!(index <= len);
if len == self.buf.capacity() {
self.reserve(1, j);
}
unsafe {
{
let p = self.buf.as_mut_ptr().add(index);
ptr::copy(p, p.offset(1), len - index);
ptr::write(p, element);
}
self.set_len(len + 1);
}
}
pub fn remove(&mut self, index: usize) -> T {
let len = self.len();
assert!(index < len);
unsafe {
let ret;
{
let ptr = self.buf.as_mut_ptr().add(index);
ret = ptr::read(ptr);
ptr::copy(ptr.offset(1), ptr, len - index - 1);
}
self.set_len(len - 1);
ret
}
}
pub fn retain<F>(&mut self, mut f: F)
where
F: FnMut(&T) -> bool,
{
let len = self.len();
let mut del = 0;
{
let v = self.to_slice_mut();
for i in 0..len {
if !f(&v[i]) {
del += 1;
} else if del > 0 {
v.swap(i - del, i);
}
}
}
if del > 0 {
self.truncate(len - del);
}
}
#[inline]
pub fn push(&mut self, value: T, j: &Journal<A>) {
if self.len == self.buf.capacity() {
self.reserve(1, j);
}
unsafe {
let end = self.buf.as_mut_ptr().add(self.len);
ptr::write(end, value);
self.len += 1;
}
}
#[inline]
pub fn pop(&mut self) -> Option<T> {
if self.len == 0 {
None
} else {
unsafe {
self.len -= 1;
Some(ptr::read(self.buf.get_unchecked(self.len())))
}
}
}
#[inline]
pub fn append(&mut self, other: &mut Self, j: &Journal<A>) {
unsafe {
self.extend_from_slice(other.as_slice(), j);
other.set_len(0);
}
}
#[inline]
pub fn clear(&mut self) {
self.truncate(0);
}
#[inline]
pub(crate) unsafe fn free_nolog(&mut self) {
if A::valid(self) && self.capacity() > 0 {
A::free_nolog(Self::__to_slice_mut(self.off(), self.capacity()));
}
self.buf.set_cap(0);
self.len = 0;
}
pub fn cast<U, F: Fn(&T) -> U>(&self, f: F) -> std::vec::Vec<U> {
let mut res = std::vec::Vec::<U>::with_capacity(self.len);
for v in self {
res.push(f(v));
}
res
}
}
impl<T: PSafe, A: MemPool> Drop for Vec<T, A> {
fn drop(&mut self) {
unsafe {
let s = self.to_slice_mut();
ptr::drop_in_place(s);
A::free_slice(self.buf.as_slice_mut());
}
}
}
impl<A: MemPool, T: PSafe, I: SliceIndex<[T]>> Index<I> for Vec<T, A> {
type Output = I::Output;
#[inline]
fn index(&self, index: I) -> &Self::Output {
Index::index(&**self, index)
}
}
impl<T: PSafe, A: MemPool> std::ops::Deref for Vec<T, A> {
type Target = [T];
fn deref(&self) -> &[T] {
self.as_slice()
}
}
impl<T: PSafe + Debug, A: MemPool> Debug for Vec<T, A> {
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), std::fmt::Error> {
let len = self.len();
write!(f, "[")?;
if len > 0 {
write!(f, "{:?}", self.get(0))?;
}
for i in 1..len {
write!(f, ", {:?}", self.get(i))?;
}
write!(f, "]")
}
}
impl<T: PSafe + Display, A: MemPool> Display for Vec<T, A> {
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), std::fmt::Error> {
let len = self.len();
write!(f, "[")?;
if len > 0 {
write!(f, "{}", self.get(0))?;
}
for i in 1..len {
write!(f, ", {}", self.get(i))?;
}
write!(f, "]")
}
}
macro_rules! __impl_slice_eq1 {
([$($vars:tt)*] $lhs:ty, $rhs:ty, $($constraints:tt)*) => {
impl<T: PSafe, U: PSafe, A: MemPool, $($vars)*> PartialEq<$rhs> for $lhs
where
T: PartialEq<U>,
$($constraints)*
{
#[inline]
fn eq(&self, other: &$rhs) -> bool { self[..] == other[..] }
#[inline]
fn ne(&self, other: &$rhs) -> bool { self[..] != other[..] }
}
}
}
__impl_slice_eq1! { [] Vec<T, A>, Vec<U, A>, }
__impl_slice_eq1! { [] Vec<T, A>, &[U], }
__impl_slice_eq1! { [] Vec<T, A>, &mut [U], }
__impl_slice_eq1! { [const N: usize] Vec<T, A>, [U; N], }
__impl_slice_eq1! { [const N: usize] Vec<T, A>, &[U; N], }
impl<A: MemPool, T: PSafe + PartialOrd> PartialOrd for Vec<T, A> {
#[inline]
fn partial_cmp(&self, other: &Vec<T, A>) -> Option<Ordering> {
PartialOrd::partial_cmp(&**self, &**other)
}
}
impl<A: MemPool, T: PSafe + PClone<A>> PClone<A> for Vec<T, A> {
fn pclone(&self, j: &Journal<A>) -> Self {
Vec::from_slice(PClone::pclone(&self.as_slice(), j), j)
}
}
impl<A: MemPool, T: PSafe + Eq> Eq for Vec<T, A> {}
impl<A: MemPool, T: PSafe + Ord> Ord for Vec<T, A> {
#[inline]
fn cmp(&self, other: &Vec<T, A>) -> Ordering {
Ord::cmp(&**self, &**other)
}
}
impl<T: PSafe, A: MemPool> Default for Vec<T, A> {
fn default() -> Self {
Vec::empty()
}
}
impl<T: PSafe, A: MemPool> RootObj<A> for Vec<T, A> {
fn init(_: &Journal<A>) -> Self {
Vec::empty()
}
}
pub struct IntoIteratorHelper<T> {
iter: std::vec::IntoIter<T>,
}
impl<T: PSafe, A: MemPool> IntoIterator for Vec<T, A> {
type Item = T;
type IntoIter = IntoIteratorHelper<T>;
fn into_iter(self) -> Self::IntoIter {
unsafe {
IntoIteratorHelper {
iter: std::vec::Vec::from_raw_parts(
self.buf.as_mut_ptr(),
self.len,
self.buf.capacity(),
)
.into_iter(),
}
}
}
}
impl<T: PSafe> Iterator for IntoIteratorHelper<T> {
type Item = T;
fn next(&mut self) -> Option<Self::Item> {
self.iter.next()
}
}
pub struct IterHelper<'a, T> {
iter: std::slice::Iter<'a, T>,
}
impl<'a, T: PSafe, A: MemPool> IntoIterator for &'a Vec<T, A> {
type Item = &'a T;
type IntoIter = IterHelper<'a, T>;
fn into_iter(self) -> Self::IntoIter {
IterHelper {
iter: self.as_slice().iter(),
}
}
}
impl<'a, T> Iterator for IterHelper<'a, T> {
type Item = &'a T;
fn next(&mut self) -> Option<Self::Item> {
self.iter.next()
}
}
impl<T: PSafe, A: MemPool> AsRef<Vec<T, A>> for Vec<T, A> {
fn as_ref(&self) -> &Vec<T, A> {
self
}
}
impl<T: PSafe, A: MemPool> AsRef<[T]> for Vec<T, A> {
fn as_ref(&self) -> &[T] {
self
}
}
impl<T: Clone + PSafe, A: MemPool> PFrom<&[T], A> for Vec<T, A> {
fn pfrom(s: &[T], j: &Journal<A>) -> Vec<T, A> {
Vec::from_slice(s, j)
}
}
impl<T: Clone + PSafe, A: MemPool> PFrom<&mut [T], A> for Vec<T, A> {
fn pfrom(s: &mut [T], j: &Journal<A>) -> Vec<T, A> {
Vec::from_slice(s, j)
}
}
impl<T: PSafe, A: MemPool> PFrom<Box<[T]>, A> for Vec<T, A> {
fn pfrom(s: Box<[T]>, j: &Journal<A>) -> Vec<T, A> {
Vec::from_slice(s.into_vec().as_slice(), j)
}
}
impl<A: MemPool> PFrom<&str, A> for Vec<u8, A> {
fn pfrom(s: &str, j: &Journal<A>) -> Vec<u8, A> {
PFrom::pfrom(s.as_bytes(), j)
}
}
impl<A: MemPool> Vec<u8, A> {
pub fn to_str(&self) -> &str {
unsafe { std::str::from_utf8_unchecked(self.as_slice()) }
}
}
#[cfg(test)]
mod test {
use crate::RootObj;
use crate::default::*;
use crate::open_flags::*;
type A = Allocator;
#[test]
fn test_array() {
struct Root {
buf: Pbox<PRefCell<PVec<i32>>>,
}
impl RootObj<A> for Root {
fn init(j: &Journal) -> Self {
Self {
buf: Pbox::new(PRefCell::new(PVec::default()), j),
}
}
}
let root = A::open::<Root>("sb4.pool", O_CFNE).unwrap();
println!("{:?}", root.buf);
println!("usage: {} bytes", A::used());
let _ = A::transaction(|j| {
let mut buf = root.buf.borrow_mut(j);
for _ in 0..5 {
let i = buf.len() as i32;
buf.extend_from_slice(&[i + 1, i + 2, i + 3], j);
}
if crate::utils::rand() % 2 == 1 {
panic!("test");
}
});
println!("usage: {} bytes", A::used());
println!("{:?}", root.buf);
}
#[test]
fn test_resize() {
struct Root {
buf: Pbox<PRefCell<PVec<i32>>>,
}
impl RootObj<A> for Root {
fn init(j: &Journal) -> Self {
Self {
buf: Pbox::new(PRefCell::new(PVec::empty()), j),
}
}
}
let root = A::open::<Root>("sb5.pool", O_CFNE).unwrap();
println!("PRE: {:?}", root.buf);
let pre = A::used();
let _ = A::transaction(|j| {
let mut buf = root.buf.borrow_mut(j);
let i = buf.len() as i32;
buf.extend_from_slice(&[i + 1], j);
});
println!("NEXT: {:?}", root.buf);
println!(" pre usage = {} bytes", pre);
println!("post usage = {} bytes", A::used());
}
#[test]
fn test_clear() {
use crate::vec::Vec;
crate::heap::Heap::transaction::<_, _>(|j| {
let mut vec = Vec::from_slice(&[1, 2, 3], j);
vec.truncate(0);
assert_eq!(vec, []);
})
.unwrap();
}
}