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