Skip to content

Commit

Permalink
WIPvariance
Browse files Browse the repository at this point in the history
  • Loading branch information
douglas-raillard-arm committed Nov 13, 2023
1 parent 02a8a13 commit 04b5048
Showing 1 changed file with 40 additions and 17 deletions.
57 changes: 40 additions & 17 deletions tools/analysis/traceevent/src/buffer.rs
Original file line number Diff line number Diff line change
@@ -37,14 +37,16 @@ use crate::{
// Keep a BTreeMap for fast lookup and to avoid huge Vec allocation in case
// some event ids are very large. Since most traces will contain just a few
// types of events, build up the smallest mapping as it goes.
struct EventDescMap<'h, T, InitDescF> {
header: &'h Header,
cold_map: BTreeMap<EventId, &'h EventDesc>,
hot_map: BTreeMap<EventId, (&'h EventDesc, T)>,
struct EventDescMap<T, InitDescF> {
// We use *const instead of &'h here as EventDescMap is held in a Cell, which would make it
// invariant in 'h, but we want to stay covariant.
header: *const Header,
cold_map: BTreeMap<EventId, *const EventDesc>,
hot_map: BTreeMap<EventId, (*const EventDesc, T)>,
init_desc: Arc<Mutex<InitDescF>>,
}

impl<'h, T: Debug, InitDescF> Debug for EventDescMap<'h, T, InitDescF> {
impl<T: Debug, InitDescF> Debug for EventDescMap<T, InitDescF> {
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), core::fmt::Error> {
f.debug_struct("EventDescMap")
.field("cold_map", &self.cold_map)
@@ -53,7 +55,7 @@ impl<'h, T: Debug, InitDescF> Debug for EventDescMap<'h, T, InitDescF> {
}
}

impl<'h, T, InitDescF> EventDescMap<'h, T, InitDescF>
impl<'h, T, InitDescF> EventDescMap<T, InitDescF>
where
InitDescF: FnMut(&'h Header, &'h EventDesc) -> T + 'h,
{
@@ -63,23 +65,40 @@ where
cold_map: header
.event_descs()
.into_iter()
.map(|desc| (desc.id, desc))
.map(|desc| (desc.id, desc as *const EventDesc))
.collect(),
hot_map: BTreeMap::new(),
init_desc,
}
}
#[inline]
fn lookup<'edm>(&'edm mut self, id: EventId) -> Option<(&'h EventDesc, &'edm T)> {
macro_rules! as_ref {
($ptr:expr, $ty:ty) => {{
let ptr: *const $ty = $ptr;
// SAFETY: We created these pointers from &'h Header in the first place so:
// * The lifetime 'h is appropriate for values contained in an &'h Header
// * EventVisitor is holding a reference &'h Header, so the values will not get
// de-allocated under our feet.
// * There is no aliasing issue since we only manipulate shared references and
// const pointers.
let val: &'h $ty = unsafe { &*ptr };
val
}}
}
match self.hot_map.entry(id) {
Entry::Occupied(entry) => {
let (desc, x) = entry.into_mut();
let desc = as_ref!(*desc, EventDesc);
Some((desc, x))
}
Entry::Vacant(entry) => match self.cold_map.remove(&id) {
Some(desc) => {
let mut init_desc = self.init_desc.lock().unwrap();
let (desc, x) = entry.insert((desc, init_desc(self.header, desc)));
let header = as_ref!(self.header, Header);
let desc = as_ref!(desc, EventDesc);
let (desc, x) = entry.insert((desc, init_desc(header, desc)));
let desc = as_ref!(*desc, EventDesc);
Some((desc, x))
}
None => None,
@@ -95,7 +114,11 @@ pub struct EventVisitor<'i, 'h, 'edm, InitDescF, T = ()> {
pub timestamp: Timestamp,
pub buffer_id: &'h BufferId,

desc_map: Cell<Option<&'edm mut EventDescMap<'h, T, InitDescF>>>,
// Using Cell<T> here means EventVisitor is invariant in any lifetime contained in T. The
// reason for that Cell invariance is the same as why "&'a mut" is invariant in 'a. However,
// the only value we store back in the Cell is 'static (None) so that invariance is overkill.
// In order to stay invariant in 'h, we make EventDescMap use *const insteaf of &'h.
desc_map: Cell<Option<&'edm mut EventDescMap<T, InitDescF>>>,
scratch: &'i ScratchAlloc,

// Unfortunately for now OnceCell<'h> makes EventVisitor invariant in 'h:
@@ -113,7 +136,7 @@ impl<'i, 'h, 'edm, InitDescF, T> EventVisitor<'i, 'h, 'edm, InitDescF, T> {
timestamp: Timestamp,
data: &'i [u8],
scratch: &'i ScratchAlloc,
desc_map: &'edm mut EventDescMap<'h, T, InitDescF>,
desc_map: &'edm mut EventDescMap<T, InitDescF>,
) -> Self {
EventVisitor {
data,
@@ -132,12 +155,12 @@ impl<'i, 'h, 'edm, InitDescF, T> EventVisitor<'i, 'h, 'edm, InitDescF, T> {
{
self
}
// fn __check_variance_h<'h1>(self) -> EventVisitor<'i, 'h1, 'edm, InitDescF, T>
// where
// 'h: 'h1,
// {
// self
// }
fn __check_variance_h<'h1>(self) -> EventVisitor<'i, 'h1, 'edm, InitDescF, T>
where
'h: 'h1,
{
self
}
}

// Capture a lifetime syntactically to avoid E0700 when using impl in return position
@@ -609,7 +632,7 @@ struct BufferItem<'a, T, InitDescF>(
Result<
(
&'a Header,
&'a mut EventDescMap<'a, T, InitDescF>,
&'a mut EventDescMap<T, InitDescF>,
&'a BufferId,
Timestamp,
&'a [u8],

0 comments on commit 04b5048

Please sign in to comment.