inc_complete/db/
handle.rs1use std::collections::BTreeSet;
2
3use crate::{
4 Cell, Computation, Db, Storage,
5 accumulate::{Accumulate, Accumulated},
6 storage::StorageFor,
7};
8
9use super::DbGet;
10
11pub struct DbHandle<'db, S> {
17 db: &'db Db<S>,
18 current_operation: Cell,
19}
20
21impl<'db, S> DbHandle<'db, S> {
22 pub(crate) fn new(db: &'db Db<S>, current_operation: Cell) -> Self {
23 let mut cell = db.cells.get_mut(¤t_operation).unwrap();
25
26 cell.dependencies.clear();
27 cell.dependency_set.clear();
28 cell.input_dependencies.clear();
29
30 Self {
31 db,
32 current_operation,
33 }
34 }
35
36 pub fn storage(&self) -> &S {
41 self.db.storage()
42 }
43}
44
45impl<S: Storage> DbHandle<'_, S> {
46 pub fn get<C: Computation>(&self, compute: C) -> C::Output
49 where
50 S: StorageFor<C>,
51 {
52 let dependency = self.db.get_or_insert_cell(compute);
54 self.update_and_register_dependency::<C>(dependency);
55
56 self.db.get_with_cell(dependency)
58 }
59
60 fn update_and_register_dependency<C: Computation>(&self, dependency: Cell) {
62 self.update_and_register_dependency_inner(dependency, C::IS_INPUT);
63 }
64
65 fn update_and_register_dependency_inner(&self, dependency: Cell, is_input: bool) {
66 let mut cell = self.db.cells.get_mut(&self.current_operation).unwrap();
67
68 let newly_registered = cell.dependency_set.insert(dependency);
71 if newly_registered {
72 cell.dependencies.push(dependency);
73 if is_input {
74 cell.input_dependencies.insert(dependency);
75 }
76 }
77 drop(cell);
78
79 self.db.update_cell(dependency);
81
82 if !newly_registered {
83 return;
84 }
85
86 let dependency = self.db.cells.get(&dependency).unwrap();
87 let dependency_inputs = dependency.input_dependencies.clone();
88 drop(dependency);
89
90 if !dependency_inputs.is_empty() {
93 let mut cell = self.db.cells.get_mut(&self.current_operation).unwrap();
94 cell.input_dependencies.extend(dependency_inputs);
95 }
96 }
97
98 pub fn accumulate<Item>(&self, item: Item)
104 where
105 S: Accumulate<Item>,
106 {
107 self.storage().accumulate(self.current_operation, item);
108 }
109
110 pub fn get_accumulated<Item, C>(&self, compute: C) -> BTreeSet<Item>
115 where
116 C: Computation,
117 Item: 'static + Ord,
118 S: StorageFor<Accumulated<Item>> + StorageFor<C> + Accumulate<Item>,
119 {
120 let dependency = self.db.get_or_insert_cell(compute);
121 self.get_accumulated_with_cell::<Item>(dependency)
122 }
123
124 pub(crate) fn get_accumulated_with_cell<Item>(&self, cell_id: Cell) -> BTreeSet<Item>
131 where
132 Item: 'static + Ord,
133 S: StorageFor<Accumulated<Item>> + Accumulate<Item>,
134 {
135 self.update_and_register_dependency_inner(cell_id, false);
136 let dependencies = self.db.with_cell(cell_id, |cell| cell.dependencies.clone());
137
138 let computation_id = Accumulated::<Item>::computation_id();
142 let mut result: BTreeSet<Item> = dependencies
143 .into_iter()
144 .filter(|&dep| self.db.with_cell(dep, |cell| cell.computation_id) != computation_id)
147 .flat_map(|dependency| self.get(Accumulated::<Item>::new(dependency)))
148 .collect();
149
150 result.extend(self.storage().get_accumulated::<Vec<Item>>(cell_id));
151 result
152 }
153}
154
155impl<'db, S, C> DbGet<C> for DbHandle<'db, S>
156where
157 C: Computation,
158 S: Storage + StorageFor<C>,
159{
160 fn get(&self, key: C) -> C::Output {
161 self.get(key)
162 }
163}