Skip to content

Commit 6e5ef3b

Browse files
committed
add a phantom lifetime to ItemSliceSend
This prevents mutating the items concurrently with the `ItemSliceSend`. For example, before this patch, one could create two `ItemSliceSend` from the same mutable slice.
1 parent 17a7c6a commit 6e5ef3b

File tree

2 files changed

+25
-13
lines changed

2 files changed

+25
-13
lines changed

gix-pack/src/cache/delta/traverse/resolve.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,13 @@ use crate::{
1717
data::EntryRange,
1818
};
1919

20-
pub(crate) struct State<F, MBFN, T: Send> {
20+
pub(crate) struct State<'items, F, MBFN, T: Send> {
2121
pub delta_bytes: Vec<u8>,
2222
pub fully_resolved_delta_bytes: Vec<u8>,
2323
pub progress: Box<dyn Progress>,
2424
pub resolve: F,
2525
pub modify_base: MBFN,
26-
pub child_items: ItemSliceSend<Item<T>>,
26+
pub child_items: ItemSliceSend<'items, Item<T>>,
2727
}
2828

2929
#[allow(clippy::too_many_arguments)]
@@ -38,7 +38,7 @@ pub(crate) fn deltas<T, F, MBFN, E, R>(
3838
resolve,
3939
modify_base,
4040
child_items,
41-
}: &mut State<F, MBFN, T>,
41+
}: &mut State<'_, F, MBFN, T>,
4242
resolve_data: &R,
4343
hash_len: usize,
4444
threads_left: &AtomicIsize,

gix-pack/src/cache/delta/traverse/util.rs

Lines changed: 22 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,37 +1,49 @@
1+
use std::marker::PhantomData;
2+
13
use crate::cache::delta::Item;
24

3-
pub struct ItemSliceSend<T>(*mut T)
5+
pub struct ItemSliceSend<'a, T>
46
where
5-
T: Send;
7+
T: Send,
8+
{
9+
items: *mut T,
10+
phantom: PhantomData<&'a T>,
11+
}
612

7-
impl<T> ItemSliceSend<T>
13+
impl<'a, T> ItemSliceSend<'a, T>
814
where
915
T: Send,
1016
{
11-
pub fn new(items: &mut [T]) -> Self {
12-
ItemSliceSend(items.as_mut_ptr())
17+
pub fn new(items: &'a mut [T]) -> Self {
18+
ItemSliceSend {
19+
items: items.as_mut_ptr(),
20+
phantom: PhantomData,
21+
}
1322
}
1423
}
1524

1625
/// SAFETY: This would be unsafe if this would ever be abused, but it's used internally and only in a way that assure that the pointers
1726
/// don't violate aliasing rules.
18-
impl<T> Clone for ItemSliceSend<T>
27+
impl<T> Clone for ItemSliceSend<'_, T>
1928
where
2029
T: Send,
2130
{
2231
fn clone(&self) -> Self {
23-
ItemSliceSend(self.0)
32+
ItemSliceSend {
33+
items: self.items,
34+
phantom: self.phantom,
35+
}
2436
}
2537
}
2638

2739
// SAFETY: T is `Send`, and we only ever access one T at a time. And, ptrs need that assurance, I wonder if it's always right.
2840
#[allow(unsafe_code)]
29-
unsafe impl<T> Send for ItemSliceSend<T> where T: Send {}
41+
unsafe impl<T> Send for ItemSliceSend<'_, T> where T: Send {}
3042

3143
/// An item returned by `iter_root_chunks`, allowing access to the `data` stored alongside nodes in a [`Tree`].
3244
pub struct Node<'a, T: Send> {
3345
pub item: &'a mut Item<T>,
34-
pub child_items: ItemSliceSend<Item<T>>,
46+
pub child_items: ItemSliceSend<'a, Item<T>>,
3547
}
3648

3749
impl<'a, T: Send> Node<'a, T> {
@@ -66,7 +78,7 @@ impl<'a, T: Send> Node<'a, T> {
6678
// SAFETY: The resulting mutable pointer cannot be yielded by any other node.
6779
#[allow(unsafe_code)]
6880
Node {
69-
item: unsafe { &mut *children.0.add(index as usize) },
81+
item: unsafe { &mut *children.items.add(index as usize) },
7082
child_items: children.clone(),
7183
}
7284
})

0 commit comments

Comments
 (0)