1
1
use std:: any:: Any ;
2
2
use std:: fmt:: Debug ;
3
3
use std:: fmt:: Formatter ;
4
- use std:: mem:: ManuallyDrop ;
5
- use std:: sync:: Arc ;
4
+ use std:: ptr:: NonNull ;
6
5
7
6
use crate :: accumulator:: accumulated_map:: InputAccumulatedValues ;
8
- use crate :: function:: DeletedEntries ;
9
7
use crate :: revision:: AtomicRevision ;
10
8
use crate :: table:: memo:: MemoTable ;
11
9
use crate :: zalsa:: MemoIngredientIndex ;
@@ -17,21 +15,33 @@ use crate::{
17
15
18
16
use super :: { Configuration , IngredientImpl } ;
19
17
20
- #[ allow( type_alias_bounds) ]
21
- pub ( super ) type ArcMemo < ' lt , C : Configuration > = Arc < Memo < <C as Configuration >:: Output < ' lt > > > ;
22
-
23
18
impl < C : Configuration > IngredientImpl < C > {
24
19
/// Memos have to be stored internally using `'static` as the database lifetime.
25
20
/// This (unsafe) function call converts from something tied to self to static.
26
21
/// Values transmuted this way have to be transmuted back to being tied to self
27
22
/// when they are returned to the user.
28
- unsafe fn to_static < ' db > ( & ' db self , memo : ArcMemo < ' db , C > ) -> ArcMemo < ' static , C > {
29
- unsafe { std:: mem:: transmute ( memo) }
23
+ unsafe fn to_static < ' db > (
24
+ & ' db self ,
25
+ memo : NonNull < Memo < C :: Output < ' db > > > ,
26
+ ) -> NonNull < Memo < C :: Output < ' static > > > {
27
+ memo. cast ( )
30
28
}
31
29
32
30
/// Convert from an internal memo (which uses `'static`) to one tied to self
33
31
/// so it can be publicly released.
34
- unsafe fn to_self < ' db > ( & ' db self , memo : ArcMemo < ' static , C > ) -> ArcMemo < ' db , C > {
32
+ unsafe fn to_self < ' db > (
33
+ & ' db self ,
34
+ memo : NonNull < Memo < C :: Output < ' static > > > ,
35
+ ) -> NonNull < Memo < C :: Output < ' db > > > {
36
+ memo. cast ( )
37
+ }
38
+
39
+ /// Convert from an internal memo (which uses `'static`) to one tied to self
40
+ /// so it can be publicly released.
41
+ unsafe fn to_self_ref < ' db > (
42
+ & ' db self ,
43
+ memo : & ' db Memo < C :: Output < ' static > > ,
44
+ ) -> & ' db Memo < C :: Output < ' db > > {
35
45
unsafe { std:: mem:: transmute ( memo) }
36
46
}
37
47
@@ -45,17 +55,16 @@ impl<C: Configuration> IngredientImpl<C> {
45
55
& ' db self ,
46
56
zalsa : & ' db Zalsa ,
47
57
id : Id ,
48
- memo : ArcMemo < ' db , C > ,
58
+ memo : NonNull < Memo < C :: Output < ' db > > > ,
49
59
memo_ingredient_index : MemoIngredientIndex ,
50
- ) -> Option < ManuallyDrop < ArcMemo < ' db , C > > > {
60
+ ) -> Option < NonNull < Memo < C :: Output < ' db > > > > {
51
61
let static_memo = unsafe { self . to_static ( memo) } ;
52
62
let old_static_memo = unsafe {
53
63
zalsa
54
64
. memo_table_for ( id)
55
65
. insert ( memo_ingredient_index, static_memo)
56
66
} ?;
57
- let old_static_memo = ManuallyDrop :: into_inner ( old_static_memo) ;
58
- Some ( ManuallyDrop :: new ( unsafe { self . to_self ( old_static_memo) } ) )
67
+ Some ( unsafe { self . to_self ( old_static_memo) } )
59
68
}
60
69
61
70
/// Loads the current memo for `key_index`. This does not hold any sort of
@@ -66,20 +75,20 @@ impl<C: Configuration> IngredientImpl<C> {
66
75
zalsa : & ' db Zalsa ,
67
76
id : Id ,
68
77
memo_ingredient_index : MemoIngredientIndex ,
69
- ) -> Option < ArcMemo < ' db , C > > {
78
+ ) -> Option < & ' db Memo < C :: Output < ' db > > > {
70
79
let static_memo = zalsa. memo_table_for ( id) . get ( memo_ingredient_index) ?;
71
- unsafe { Some ( self . to_self ( static_memo) ) }
80
+
81
+ unsafe { Some ( self . to_self_ref ( static_memo) ) }
72
82
}
73
83
74
84
/// Evicts the existing memo for the given key, replacing it
75
85
/// with an equivalent memo that has no value. If the memo is untracked, BaseInput,
76
86
/// or has values assigned as output of another query, this has no effect.
77
87
pub ( super ) fn evict_value_from_memo_for (
78
88
table : & mut MemoTable ,
79
- deleted_entries : & DeletedEntries < C > ,
80
89
memo_ingredient_index : MemoIngredientIndex ,
81
90
) {
82
- let map = |memo : ArcMemo < ' static , C > | -> ArcMemo < ' static , C > {
91
+ let map = |memo : & mut Memo < C :: Output < ' static > > | {
83
92
match & memo. revisions . origin {
84
93
QueryOrigin :: Assigned ( _)
85
94
| QueryOrigin :: DerivedUntracked ( _)
@@ -88,43 +97,15 @@ impl<C: Configuration> IngredientImpl<C> {
88
97
// assigned as output of another query
89
98
// or those with untracked inputs
90
99
// as their values cannot be reconstructed.
91
- memo
92
100
}
93
101
QueryOrigin :: Derived ( _) => {
94
- // Note that we cannot use `Arc::get_mut` here as the use of `ArcSwap` makes it
95
- // impossible to get unique access to the interior Arc
96
- // QueryRevisions: !Clone to discourage cloning, we need it here though
97
- let & QueryRevisions {
98
- changed_at,
99
- durability,
100
- ref origin,
101
- ref tracked_struct_ids,
102
- ref accumulated,
103
- ref accumulated_inputs,
104
- } = & memo. revisions ;
105
- // Re-assemble the memo but with the value set to `None`
106
- Arc :: new ( Memo :: new (
107
- None ,
108
- memo. verified_at . load ( ) ,
109
- QueryRevisions {
110
- changed_at,
111
- durability,
112
- origin : origin. clone ( ) ,
113
- tracked_struct_ids : tracked_struct_ids. clone ( ) ,
114
- accumulated : accumulated. clone ( ) ,
115
- accumulated_inputs : accumulated_inputs. clone ( ) ,
116
- } ,
117
- ) )
102
+ // Set the memo value to `None`.
103
+ memo. value = None ;
118
104
}
119
105
}
120
106
} ;
121
- // SAFETY: We queue the old value for deletion, delaying its drop until the next revision bump.
122
- let old = unsafe { table. map_memo ( memo_ingredient_index, map) } ;
123
- if let Some ( old) = old {
124
- // In case there is a reference to the old memo out there, we have to store it
125
- // in the deleted entries. This will get cleared when a new revision starts.
126
- deleted_entries. push ( ManuallyDrop :: into_inner ( old) ) ;
127
- }
107
+
108
+ table. map_memo ( memo_ingredient_index, map)
128
109
}
129
110
}
130
111
0 commit comments