@@ -7,7 +7,9 @@ use std::sync::Arc;
7
7
use crossbeam:: atomic:: AtomicCell ;
8
8
9
9
use crate :: accumulator:: accumulated_map:: InputAccumulatedValues ;
10
+ use crate :: plumbing:: MemoDropSender ;
10
11
use crate :: table:: memo:: MemoTable ;
12
+ use crate :: zalsa:: MemoIngredientIndex ;
11
13
use crate :: zalsa_local:: QueryOrigin ;
12
14
use crate :: {
13
15
key:: DatabaseKeyIndex , zalsa:: Zalsa , zalsa_local:: QueryRevisions , Event , EventKind , Id ,
@@ -68,7 +70,11 @@ impl<C: Configuration> IngredientImpl<C> {
68
70
/// Evicts the existing memo for the given key, replacing it
69
71
/// with an equivalent memo that has no value. If the memo is untracked, BaseInput,
70
72
/// or has values assigned as output of another query, this has no effect.
71
- pub ( super ) fn evict_value_from_memo_for ( & self , table : & mut MemoTable ) {
73
+ pub ( super ) fn evict_value_from_memo_for (
74
+ table : & mut MemoTable ,
75
+ memo_ingredient_index : MemoIngredientIndex ,
76
+ memo_drop : & MemoDropSender ,
77
+ ) {
72
78
let map = |memo : ArcMemo < ' static , C > | -> ArcMemo < ' static , C > {
73
79
match & memo. revisions . origin {
74
80
QueryOrigin :: Assigned ( _)
@@ -82,37 +88,17 @@ impl<C: Configuration> IngredientImpl<C> {
82
88
}
83
89
QueryOrigin :: Derived ( _) => {
84
90
// Note that we cannot use `Arc::get_mut` here as the use of `ArcSwap` makes it
85
- // impossible to get unique access to the interior Arc
86
- // QueryRevisions: !Clone to discourage cloning, we need it here though
87
- let & QueryRevisions {
88
- changed_at,
89
- durability,
90
- ref origin,
91
- ref tracked_struct_ids,
92
- ref accumulated,
93
- ref accumulated_inputs,
94
- } = & memo. revisions ;
95
- // Re-assemble the memo but with the value set to `None`
96
- Arc :: new ( Memo :: new (
97
- None ,
98
- memo. verified_at . load ( ) ,
99
- QueryRevisions {
100
- changed_at,
101
- durability,
102
- origin : origin. clone ( ) ,
103
- tracked_struct_ids : tracked_struct_ids. clone ( ) ,
104
- accumulated : accumulated. clone ( ) ,
105
- accumulated_inputs : AtomicCell :: new ( accumulated_inputs. load ( ) ) ,
106
- } ,
107
- ) )
91
+ // impossible to get unique access to the interior Arc so we need to construct
92
+ // a new allocation
93
+ Arc :: new ( memo. without_value ( ) )
108
94
}
109
95
}
110
96
} ;
111
97
// SAFETY: We queue the old value for deletion, delaying its drop until the next revision
112
98
// bump.
113
- let old_memo = unsafe { table. map_memo ( self . memo_ingredient_index , map) } ;
99
+ let old_memo = unsafe { table. map_memo ( memo_ingredient_index, map) } ;
114
100
if let Some ( old_memo) = old_memo {
115
- self . delete . delay ( ManuallyDrop :: into_inner ( old_memo) ) ;
101
+ memo_drop . delay ( ManuallyDrop :: into_inner ( old_memo) ) ;
116
102
}
117
103
}
118
104
}
@@ -143,6 +129,31 @@ impl<V> Memo<V> {
143
129
revisions,
144
130
}
145
131
}
132
+
133
+ pub ( super ) fn without_value ( & self ) -> Self {
134
+ let & QueryRevisions {
135
+ changed_at,
136
+ durability,
137
+ ref origin,
138
+ ref tracked_struct_ids,
139
+ ref accumulated,
140
+ ref accumulated_inputs,
141
+ } = & self . revisions ;
142
+ // Re-assemble the memo but with the value set to `None`
143
+ Memo :: new (
144
+ None ,
145
+ self . verified_at . load ( ) ,
146
+ QueryRevisions {
147
+ changed_at,
148
+ durability,
149
+ origin : origin. clone ( ) ,
150
+ tracked_struct_ids : tracked_struct_ids. clone ( ) ,
151
+ accumulated : accumulated. clone ( ) ,
152
+ accumulated_inputs : AtomicCell :: new ( accumulated_inputs. load ( ) ) ,
153
+ } ,
154
+ )
155
+ }
156
+
146
157
/// True if this memo is known not to have changed based on its durability.
147
158
pub ( super ) fn check_durability ( & self , zalsa : & Zalsa ) -> bool {
148
159
let last_changed = zalsa. last_changed_revision ( self . revisions . durability ) ;
0 commit comments