1 // Copyright 2023 Google LLC
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //     http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 use crate::Handle;
16 use core::ops::{Deref, DerefMut};
17 use lock_adapter::stdlib::RwMapping;
18 use std::collections::HashMap;
19 use std::marker::PhantomData;
20 
21 /// A RAII read lock guard for an object in a [`HandleMap`](crate::HandleMap)
22 /// pointed-to by a given [`Handle`]. When this struct is
23 /// dropped, the underlying read lock on the associated
24 /// shard will be dropped.
25 pub struct ObjectReadGuardImpl<'a, T: 'a> {
26     pub(crate) guard: lock_adapter::stdlib::MappedRwLockReadGuard<
27         'a,
28         <Self as ObjectReadGuard>::Arg,
29         <Self as ObjectReadGuard>::Ret,
30         <Self as ObjectReadGuard>::Mapping,
31     >,
32 }
33 
34 /// Trait implemented for an ObjectReadGuard which defines the associated types of the guard and a
35 /// mapping for how the guard is retrieved from its parent object
36 pub trait ObjectReadGuard: Deref<Target = Self::Ret> {
37     /// The mapping which defines how a guard is retrieved for `Self::Ret` from `Self::Arg`
38     type Mapping: RwMapping<Arg = Self::Arg, Ret = Self::Ret>;
39     /// The argument type input to the mapping functions
40     type Arg;
41     /// The Return type of the mapping functions
42     type Ret;
43 }
44 
45 impl<'a, T> Deref for ObjectReadGuardImpl<'a, T> {
46     type Target = T;
47 
deref(&self) -> &Self::Target48     fn deref(&self) -> &Self::Target {
49         self.guard.deref()
50     }
51 }
52 
53 pub struct ObjectReadGuardMapping<'a, T> {
54     pub(crate) handle: Handle,
55     pub(crate) _marker: PhantomData<&'a T>,
56 }
57 
58 impl<'a, T> RwMapping for ObjectReadGuardMapping<'a, T> {
59     type Arg = HashMap<Handle, T>;
60     type Ret = T;
61 
map<'b>(&self, arg: &'b Self::Arg) -> &'b Self::Ret62     fn map<'b>(&self, arg: &'b Self::Arg) -> &'b Self::Ret {
63         #[allow(clippy::expect_used)]
64         arg.get(&self.handle).expect("We know that the entry exists, since we've locked the shard and already checked that it exists prior to handing out this new, mapped read-lock.")
65     }
66 
map_mut<'b>(&self, arg: &'b mut Self::Arg) -> &'b mut Self::Ret67     fn map_mut<'b>(&self, arg: &'b mut Self::Arg) -> &'b mut Self::Ret {
68         #[allow(clippy::expect_used)]
69         arg.get_mut(&self.handle).expect("We know that the entry exists, since we've locked the shard and already checked that it exists prior to handing out this new, mapped read-lock.")
70     }
71 }
72 
73 impl<'a, T> ObjectReadGuard for ObjectReadGuardImpl<'a, T> {
74     type Mapping = ObjectReadGuardMapping<'a, T>;
75     type Arg = HashMap<Handle, T>;
76     type Ret = T;
77 }
78 
79 /// A RAII read-write lock guard for an object in a [`HandleMap`](crate::HandleMap)
80 /// pointed-to by a given [`Handle`]. When this struct is
81 /// dropped, the underlying read-write lock on the associated
82 /// shard will be dropped.
83 pub struct ObjectReadWriteGuardImpl<'a, T: 'a> {
84     pub(crate) guard: lock_adapter::stdlib::MappedRwLockWriteGuard<
85         'a,
86         <Self as ObjectReadWriteGuard>::Arg,
87         <Self as ObjectReadWriteGuard>::Ret,
88         <Self as ObjectReadWriteGuard>::Mapping,
89     >,
90 }
91 
92 /// Trait implemented for an object read guard which defines the associated types of the guard and a
93 /// mapping for how the guard is retrieved from its parent object
94 pub trait ObjectReadWriteGuard: Deref<Target = Self::Ret> + DerefMut<Target = Self::Ret> {
95     /// The mapping which defines how a guard is retrieved for `Ret` from `Arg`
96     type Mapping: RwMapping<Arg = Self::Arg, Ret = Self::Ret>;
97     /// The argument type input to the mapping functions
98     type Arg;
99     /// The Return type of the mapping functions
100     type Ret;
101 }
102 
103 pub struct ObjectReadWriteGuardMapping<'a, T> {
104     pub(crate) handle: Handle,
105     pub(crate) _marker: PhantomData<&'a T>,
106 }
107 
108 impl<'a, T> Deref for ObjectReadWriteGuardImpl<'a, T> {
109     type Target = T;
110 
deref(&self) -> &Self::Target111     fn deref(&self) -> &Self::Target {
112         self.guard.deref()
113     }
114 }
115 
116 impl<'a, T> DerefMut for ObjectReadWriteGuardImpl<'a, T> {
deref_mut(&mut self) -> &mut Self::Target117     fn deref_mut(&mut self) -> &mut Self::Target {
118         self.guard.deref_mut()
119     }
120 }
121 
122 impl<'a, T> ObjectReadWriteGuard for ObjectReadWriteGuardImpl<'a, T> {
123     type Mapping = ObjectReadWriteGuardMapping<'a, T>;
124     type Arg = HashMap<Handle, T>;
125     type Ret = T;
126 }
127 
128 impl<'a, T> RwMapping for ObjectReadWriteGuardMapping<'a, T> {
129     type Arg = HashMap<Handle, T>;
130     type Ret = T;
131 
map<'b>(&self, arg: &'b Self::Arg) -> &'b Self::Ret132     fn map<'b>(&self, arg: &'b Self::Arg) -> &'b Self::Ret {
133         #[allow(clippy::expect_used)]
134         arg.get(&self.handle)
135             .expect("Caller must verify that provided hande exists")
136     }
137 
map_mut<'b>(&self, arg: &'b mut Self::Arg) -> &'b mut Self::Ret138     fn map_mut<'b>(&self, arg: &'b mut Self::Arg) -> &'b mut Self::Ret {
139         #[allow(clippy::expect_used)]
140         arg.get_mut(&self.handle)
141             .expect("Caller must verify that provided hande exists")
142     }
143 }
144