blob: 486cfd5eece877ce1230a799555e4031f2760cf4 [file] [log] [blame]
// Copyright 2023 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
use crate::shard::{ShardMap, ShardValue};
use crate::Handle;
use lock_adapter::mapped_guard::RwMapping;
use std::marker::PhantomData;
/// A generic mapped read guard implementation.
pub(crate) use lock_adapter::stdlib::MappedRwLockReadGuard as ReadGuard;
/// A generic mapped read-write guard implementation.
pub(crate) use lock_adapter::stdlib::MappedRwLockWriteGuard as ReadWriteGuard;
/// The RwLock implementation to use
pub(crate) use lock_adapter::stdlib::RwLock;
/// The RwLock read guard implementation to use. Needs to be mapped to a value before being passed
/// to clients.
pub(crate) use lock_adapter::stdlib::RwLockReadGuard as RawReadGuard;
/// The RwLock read-write guard implementation to use. Needs to be mapped to a value before being
/// passed to clients.
pub(crate) use lock_adapter::stdlib::RwLockWriteGuard as RawReadWriteGuard;
/// An [`RwMapping`] implementation that looks up a type-erased [`ShardValue`] from a [`ShardMap`]
/// with a given [`Handle`].
pub struct LookupByHandle {
handle: Handle,
}
impl LookupByHandle {
/// Create a mapping from the given [`Handle`]. This handle must exist in the guard's contained
/// [`ShardMap`]; if not, the mapping functions may panic.
pub fn new(handle: Handle) -> Self {
Self { handle }
}
}
impl RwMapping for LookupByHandle {
type Arg = ShardMap;
type Ret = ShardValue;
fn map<'a>(&self, arg: &'a Self::Arg) -> &'a Self::Ret {
#[allow(clippy::expect_used)]
arg.get(&self.handle)
.expect("Caller must verify that provided handle exists")
}
fn map_mut<'a>(&self, arg: &'a mut Self::Arg) -> &'a mut Self::Ret {
#[allow(clippy::expect_used)]
arg.get_mut(&self.handle)
.expect("Caller must verify that provided handle exists")
}
}
/// An [`RwMapping`] implementation that performs downcast on a type-erased [`ShardValue`]
/// instance. This is used to undo type erasure before giving a guard to a client. Type-erased
/// values are always `'static`.
pub struct Downcast<T> {
/// Keep `T` around for use in `impl RwMapping`.
_t: PhantomData<fn(T) -> T>,
}
impl<T: 'static> Downcast<T> {
pub fn new() -> Self {
Self { _t: PhantomData }
}
}
impl<T: 'static> RwMapping for Downcast<T> {
type Arg = ShardValue;
type Ret = T;
fn map<'a>(&self, arg: &'a Self::Arg) -> &'a Self::Ret {
#[allow(clippy::expect_used)]
arg.downcast_ref::<T>()
.expect("Caller must verify the type is correct")
}
fn map_mut<'a>(&self, arg: &'a mut Self::Arg) -> &'a mut Self::Ret {
#[allow(clippy::expect_used)]
arg.downcast_mut::<T>()
.expect("Caller must verify the type is correct")
}
}