mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2026-09-29 17:28:12 +08:00
Rederive the shared source pointer through an unwinding set_layout
This commit is contained in:
@@ -127,12 +127,22 @@ impl<N: ?Sized> SharedSource<N> {
|
|||||||
|
|
||||||
/// Re-derives the cached pointer from the owned payload. An exclusive
|
/// Re-derives the cached pointer from the owned payload. An exclusive
|
||||||
/// re-borrow of the payload invalidates the pointer taken before it, so
|
/// re-borrow of the payload invalidates the pointer taken before it, so
|
||||||
/// every mutation through `own` ends here.
|
/// every mutation through `own` ends here, an unwinding one included.
|
||||||
pub fn rederive(&mut self) {
|
pub fn rederive(&mut self) {
|
||||||
self.ptr = std::ptr::NonNull::from(&*self.own);
|
self.ptr = std::ptr::NonNull::from(&*self.own);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Re-derives on the way out of an exclusive re-borrow, so a mutation that
|
||||||
|
/// panics cannot leave the cached pointer retired for a caller that catches.
|
||||||
|
struct Rederive<'a, N: ?Sized>(&'a mut SharedSource<N>);
|
||||||
|
|
||||||
|
impl<N: ?Sized> Drop for Rederive<'_, N> {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
self.0.rederive();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// SAFETY: `ptr` is derived from the owned Arc and never mutated through, so the source is exactly as
|
// SAFETY: `ptr` is derived from the owned Arc and never mutated through, so the source is exactly as
|
||||||
// thread safe as the payload it shares.
|
// thread safe as the payload it shares.
|
||||||
unsafe impl<N: ?Sized + Send + Sync> Send for SharedSource<N> {}
|
unsafe impl<N: ?Sized + Send + Sync> Send for SharedSource<N> {}
|
||||||
@@ -224,9 +234,11 @@ impl SourceHandle {
|
|||||||
layout: |edge| Node::<ContextImpl>::layout(edge.downcast_ref::<SharedSource<N>>().expect("layout hook matches the stored edge type")),
|
layout: |edge| Node::<ContextImpl>::layout(edge.downcast_ref::<SharedSource<N>>().expect("layout hook matches the stored edge type")),
|
||||||
set_layout: |edge, layout| {
|
set_layout: |edge, layout| {
|
||||||
let shared = edge.downcast_mut::<SharedSource<N>>().expect("set_layout hook matches the stored edge type");
|
let shared = edge.downcast_mut::<SharedSource<N>>().expect("set_layout hook matches the stored edge type");
|
||||||
let node = std::sync::Arc::get_mut(&mut shared.own).expect("layout is installed before the node is shared");
|
// The re-borrow below retires the cached pointer, so the rederive
|
||||||
|
// is a guard: a panicking `set_layout` must not leave it stale.
|
||||||
|
let guard = Rederive(shared);
|
||||||
|
let node = std::sync::Arc::get_mut(&mut guard.0.own).expect("layout is installed before the node is shared");
|
||||||
Node::<ContextImpl>::set_layout(node, layout);
|
Node::<ContextImpl>::set_layout(node, layout);
|
||||||
shared.rederive();
|
|
||||||
},
|
},
|
||||||
ty,
|
ty,
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user