use parking_lot::{ArcRwLockReadGuard, RwLockReadGuard};
use re_chunk_store::{ChunkStore, ChunkStoreHandle};
use crate::{QueryCache, QueryCacheHandle};
pub trait StorageEngineLike {
fn with<F: FnOnce(&ChunkStore, &QueryCache) -> R, R>(&self, f: F) -> R;
fn try_with<F: FnOnce(&ChunkStore, &QueryCache) -> R, R>(&self, f: F) -> Option<R> {
Some(self.with(f))
}
}
#[derive(Clone)]
pub struct StorageEngine {
store: ChunkStoreHandle,
cache: QueryCacheHandle,
}
impl StorageEngineLike for StorageEngine {
#[inline]
fn with<F: FnOnce(&ChunkStore, &QueryCache) -> R, R>(&self, f: F) -> R {
let this = self.read();
f(this.store(), this.cache())
}
#[inline]
fn try_with<F: FnOnce(&ChunkStore, &QueryCache) -> R, R>(&self, f: F) -> Option<R> {
let this = self.try_read()?;
Some(f(this.store(), this.cache()))
}
}
impl StorageEngine {
#[inline]
#[allow(unsafe_code)]
pub unsafe fn new(store: ChunkStoreHandle, cache: QueryCacheHandle) -> Self {
Self { store, cache }
}
}
impl StorageEngine {
#[inline]
pub fn read(&self) -> StorageEngineReadGuard<'_> {
StorageEngineReadGuard {
cache: self.cache.read(),
store: self.store.read(),
}
}
#[inline]
pub fn try_read(&self) -> Option<StorageEngineReadGuard<'_>> {
let cache = self.cache.try_read()?;
let store = self.store.try_read()?;
Some(StorageEngineReadGuard { cache, store })
}
#[inline]
pub fn try_read_arc(&self) -> Option<StorageEngineArcReadGuard> {
let cache = self.cache.try_read_arc()?;
let store = self.store.try_read_arc()?;
Some(StorageEngineArcReadGuard { cache, store })
}
#[inline]
pub fn write(&self) -> StorageEngineWriteGuard<'_> {
StorageEngineWriteGuard {
cache: self.cache.write(),
store: self.store.write(),
}
}
#[inline]
pub fn try_write(&self) -> Option<StorageEngineWriteGuard<'_>> {
let cache = self.cache.try_write()?;
let store = self.store.try_write()?;
Some(StorageEngineWriteGuard { cache, store })
}
#[inline]
pub fn read_arc(&self) -> StorageEngineArcReadGuard {
StorageEngineArcReadGuard {
cache: self.cache.read_arc(),
store: self.store.read_arc(),
}
}
#[inline]
pub fn write_arc(&self) -> StorageEngineArcWriteGuard {
StorageEngineArcWriteGuard {
cache: self.cache.write_arc(),
store: self.store.write_arc(),
}
}
#[inline]
pub fn try_write_arc(&self) -> Option<StorageEngineArcWriteGuard> {
let cache = self.cache.try_write_arc()?;
let store = self.store.try_write_arc()?;
Some(StorageEngineArcWriteGuard { cache, store })
}
}
pub struct StorageEngineReadGuard<'a> {
store: parking_lot::RwLockReadGuard<'a, ChunkStore>,
cache: parking_lot::RwLockReadGuard<'a, QueryCache>,
}
impl Clone for StorageEngineReadGuard<'_> {
fn clone(&self) -> Self {
Self {
store: parking_lot::RwLock::read(RwLockReadGuard::rwlock(&self.store)),
cache: parking_lot::RwLock::read(RwLockReadGuard::rwlock(&self.cache)),
}
}
}
impl StorageEngineReadGuard<'_> {
#[inline]
pub fn store(&self) -> &ChunkStore {
&self.store
}
#[inline]
pub fn cache(&self) -> &QueryCache {
&self.cache
}
}
impl StorageEngineLike for StorageEngineReadGuard<'_> {
#[inline]
fn with<F: FnOnce(&ChunkStore, &QueryCache) -> R, R>(&self, f: F) -> R {
f(self.store(), self.cache())
}
}
pub struct StorageEngineArcReadGuard {
store: parking_lot::ArcRwLockReadGuard<parking_lot::RawRwLock, ChunkStore>,
cache: parking_lot::ArcRwLockReadGuard<parking_lot::RawRwLock, QueryCache>,
}
impl StorageEngineArcReadGuard {
#[inline]
pub fn store(&self) -> &ChunkStore {
&self.store
}
#[inline]
pub fn cache(&self) -> &QueryCache {
&self.cache
}
}
impl StorageEngineLike for StorageEngineArcReadGuard {
#[inline]
fn with<F: FnOnce(&ChunkStore, &QueryCache) -> R, R>(&self, f: F) -> R {
f(self.store(), self.cache())
}
}
impl Clone for StorageEngineArcReadGuard {
fn clone(&self) -> Self {
Self {
store: parking_lot::RwLock::read_arc(ArcRwLockReadGuard::rwlock(&self.store)),
cache: parking_lot::RwLock::read_arc(ArcRwLockReadGuard::rwlock(&self.cache)),
}
}
}
pub struct StorageEngineWriteGuard<'a> {
store: parking_lot::RwLockWriteGuard<'a, ChunkStore>,
cache: parking_lot::RwLockWriteGuard<'a, QueryCache>,
}
impl<'a> StorageEngineWriteGuard<'a> {
#[inline]
pub fn downgrade(self) -> StorageEngineReadGuard<'a> {
StorageEngineReadGuard {
store: parking_lot::RwLockWriteGuard::downgrade(self.store),
cache: parking_lot::RwLockWriteGuard::downgrade(self.cache),
}
}
}
impl StorageEngineWriteGuard<'_> {
#[inline]
pub fn store(&mut self) -> &mut ChunkStore {
&mut self.store
}
#[inline]
pub fn cache(&mut self) -> &mut QueryCache {
&mut self.cache
}
}
pub struct StorageEngineArcWriteGuard {
store: parking_lot::ArcRwLockWriteGuard<parking_lot::RawRwLock, ChunkStore>,
cache: parking_lot::ArcRwLockWriteGuard<parking_lot::RawRwLock, QueryCache>,
}
impl StorageEngineArcWriteGuard {
#[inline]
pub fn downgrade(self) -> StorageEngineArcReadGuard {
StorageEngineArcReadGuard {
store: parking_lot::ArcRwLockWriteGuard::downgrade(self.store),
cache: parking_lot::ArcRwLockWriteGuard::downgrade(self.cache),
}
}
}
impl StorageEngineArcWriteGuard {
#[inline]
pub fn store(&mut self) -> &mut ChunkStore {
&mut self.store
}
#[inline]
pub fn cache(&mut self) -> &mut QueryCache {
&mut self.cache
}
}