diff options
author | Justus Winter <justus@sequoia-pgp.org> | 2023-03-22 09:44:35 +0100 |
---|---|---|
committer | Justus Winter <justus@sequoia-pgp.org> | 2023-03-22 09:44:35 +0100 |
commit | 5202e7f23579861db7ecbf5970a8416b306d73b2 (patch) | |
tree | de2788a029e52d8edab9b3a8b8e8d83cc8066426 | |
parent | c7b40bcd1a66419e737718c6ccebb09826b26cc4 (diff) |
openpgp: When looking up subpackets, acquire the lock just once.
-rw-r--r-- | openpgp/src/packet/signature/subpacket.rs | 32 |
1 files changed, 19 insertions, 13 deletions
diff --git a/openpgp/src/packet/signature/subpacket.rs b/openpgp/src/packet/signature/subpacket.rs index e2c8e73a..f0f878ec 100644 --- a/openpgp/src/packet/signature/subpacket.rs +++ b/openpgp/src/packet/signature/subpacket.rs @@ -58,7 +58,7 @@ use std::cmp::Ordering; use std::collections::HashMap; use std::convert::{TryInto, TryFrom}; use std::hash::{Hash, Hasher}; -use std::sync::Mutex; +use std::sync::{Mutex, MutexGuard}; use std::ops::{Deref, DerefMut}; use std::fmt; use std::cmp; @@ -676,17 +676,25 @@ impl SubpacketArea { Ok(area) } - // Initialize `Signature::hashed_area_parsed` from - // `Signature::hashed_area`, if necessary. - fn cache_init(&self) { - if self.parsed.lock().unwrap().borrow().is_none() { + /// Initialize the cache mapping subpacket tags to positions in + /// the subpacket area. + /// + /// If the cache is already initialized, this is a NOP. + /// + /// Returns the locked cache. + fn cache_init(&self) + -> MutexGuard<'_, RefCell<Option<HashMap<SubpacketTag, usize>>>> + { + let cache = self.parsed.lock().unwrap(); + if cache.borrow().is_none() { let mut hash = HashMap::new(); for (i, sp) in self.packets.iter().enumerate() { hash.insert(sp.tag(), i); } - *self.parsed.lock().unwrap().borrow_mut() = Some(hash); + *cache.borrow_mut() = Some(hash); } + cache } /// Invalidates the cache. @@ -793,9 +801,7 @@ impl SubpacketArea { /// # } /// ``` pub fn subpacket(&self, tag: SubpacketTag) -> Option<&Subpacket> { - self.cache_init(); - - match self.parsed.lock().unwrap().borrow().as_ref().unwrap().get(&tag) { + match self.cache_init().borrow().as_ref().unwrap().get(&tag) { Some(&n) => Some(&self.packets[n]), None => None, } @@ -854,10 +860,10 @@ impl SubpacketArea { /// ``` pub fn subpacket_mut(&mut self, tag: SubpacketTag) -> Option<&mut Subpacket> { - self.cache_init(); - - match self.parsed.lock().unwrap().borrow().as_ref().unwrap().get(&tag) { - Some(&n) => Some(&mut self.packets[n]), + let n = self.cache_init().borrow().as_ref().unwrap().get(&tag).cloned(); + // Cache is dropped here so that we can mutably borrow self.packets. + match n { + Some(n) => Some(&mut self.packets[n]), None => None, } } |