Skip to content

Commit 21f66f9

Browse files
add cleanliness of next_ir function with Todo struct
1 parent 3954fc4 commit 21f66f9

File tree

1 file changed

+95
-85
lines changed

1 file changed

+95
-85
lines changed

src/scheduler.rs

Lines changed: 95 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,30 @@ use patronus::expr::Context;
1818
use patronus::sim::Interpreter;
1919
use patronus::system::TransitionSystem;
2020

21+
#[derive(Debug, Clone)]
22+
pub struct Todo<'a> {
23+
pub tr: &'a Transaction,
24+
pub st: &'a SymbolTable,
25+
pub args: HashMap<&'a str, BitVecValue>,
26+
pub next_stmt_map: FxHashMap<StmtId, Option<StmtId>>,
27+
}
28+
29+
impl<'a> Todo<'a> {
30+
pub fn new(
31+
tr: &'a Transaction,
32+
st: &'a SymbolTable,
33+
args: HashMap<&'a str, BitVecValue>,
34+
next_stmt_map: FxHashMap<StmtId, Option<StmtId>>,
35+
) -> Self {
36+
Self {
37+
tr,
38+
st,
39+
args,
40+
next_stmt_map,
41+
}
42+
}
43+
}
44+
2145
#[derive(Debug, Clone)]
2246
pub struct Thread<'a> {
2347
pub tr: &'a Transaction,
@@ -26,29 +50,26 @@ pub struct Thread<'a> {
2650
pub next_step: Option<StmtId>,
2751
args: HashMap<&'a str, BitVecValue>,
2852
next_stmt_map: FxHashMap<StmtId, Option<StmtId>>,
29-
/// Index into the original `todos` (used to store this threads result)
53+
/// Index into the original `todos` (used to store this thread's result)
3054
thread_id: usize,
3155
}
3256

3357
impl<'a> Thread<'a> {
3458
pub fn initialize_thread(
35-
tr: &'a Transaction,
36-
st: &'a SymbolTable,
37-
args: HashMap<&'a str, BitVecValue>,
38-
next_stmt_map: FxHashMap<StmtId, Option<StmtId>>,
59+
todo: Todo<'a>,
3960
thread_id: usize,
4061
) -> Self {
4162
println!(
4263
"Thread initialized with transaction: {:?}, thread_id={}",
43-
tr.name, thread_id
64+
todo.tr.name, thread_id
4465
);
4566
Self {
46-
tr,
47-
st,
48-
current_step: tr.body,
67+
tr: todo.tr,
68+
st: todo.st,
69+
current_step: todo.tr.body,
4970
next_step: None,
50-
args,
51-
next_stmt_map,
71+
args: todo.args,
72+
next_stmt_map: todo.next_stmt_map,
5273
thread_id,
5374
}
5475
}
@@ -69,6 +90,41 @@ pub struct Scheduler<'a> {
6990
}
7091

7192
impl<'a> Scheduler<'a> {
93+
// Helper method that creates a Todo struct
94+
fn create_todo_helper(
95+
todos: &[(usize, Vec<BitVecValue>)],
96+
idx: usize,
97+
irs: &[(&'a Transaction, &'a SymbolTable)],
98+
next_stmt_mappings: &[FxHashMap<StmtId, Option<StmtId>>],
99+
) -> Option<Todo<'a>> {
100+
if idx < todos.len() {
101+
// get the corresponding transaction and symbol table
102+
let ir_idx = todos[idx].0;
103+
let (tr, st) = irs[ir_idx];
104+
105+
// setup the arguments for the transaction
106+
let args = todos[idx].1.clone();
107+
let mut args_map = HashMap::new();
108+
109+
// setup the next_stmt_mapping from the parallel vector
110+
let next_stmt_map = next_stmt_mappings[ir_idx].clone();
111+
112+
for (i, arg) in args.iter().enumerate() {
113+
let identifier = st[tr.args[i].symbol()].name();
114+
args_map.insert(identifier, arg.clone());
115+
}
116+
117+
Some(Todo::new(tr, st, args_map, next_stmt_map))
118+
} else {
119+
None
120+
}
121+
}
122+
123+
// Instance method that uses self fields and returns a Todo
124+
fn next_todo(&self, idx: usize) -> Option<Todo<'a>> {
125+
Self::create_todo_helper(&self.todos, idx, &self.irs, &self.next_stmt_maps)
126+
}
127+
72128
pub fn new(
73129
irs: Vec<(&'a Transaction, &'a SymbolTable)>,
74130
todos: Vec<(usize, Vec<BitVecValue>)>,
@@ -83,31 +139,24 @@ impl<'a> Scheduler<'a> {
83139

84140
// setup the Evaluator and first Thread
85141
let next_todo_idx = 0;
86-
let res = Self::next_ir(&todos, next_todo_idx, irs.clone(), next_stmt_maps.clone());
87-
let (initial_tr, initial_st, initial_args, initial_next_stmt_map) =
88-
res.expect("No transactions passed.");
142+
let initial_todo = Self::create_todo_helper(&todos, next_todo_idx, &irs, &next_stmt_maps)
143+
.expect("No transactions passed.");
89144

90-
println!("Starting with initial transaction: {:?}", initial_tr.name);
145+
println!("Starting with initial transaction: {:?}", initial_todo.tr.name);
91146

92147
// Initialize evaluator with first transaction
93148
let evaluator = Evaluator::new(
94-
initial_args.clone(),
95-
initial_tr,
96-
initial_st,
149+
initial_todo.args.clone(),
150+
initial_todo.tr,
151+
initial_todo.st,
97152
handler,
98153
ctx,
99154
sys,
100155
sim,
101156
);
102157

103158
let results_size = todos.len();
104-
let first = Thread::initialize_thread(
105-
initial_tr,
106-
initial_st,
107-
initial_args,
108-
initial_next_stmt_map,
109-
next_todo_idx,
110-
);
159+
let first = Thread::initialize_thread(initial_todo, next_todo_idx);
111160
println!("Added first thread to active_threads");
112161
Self {
113162
irs,
@@ -123,41 +172,6 @@ impl<'a> Scheduler<'a> {
123172
}
124173
}
125174

126-
// TODO: simplify this ugly return type and I think this should just take &self as an argument.
127-
fn next_ir(
128-
todos: &[(usize, Vec<BitVecValue>)],
129-
idx: usize,
130-
irs: Vec<(&'a Transaction, &'a SymbolTable)>,
131-
next_stmt_mappings: Vec<FxHashMap<StmtId, Option<StmtId>>>,
132-
) -> Option<(
133-
&'a Transaction,
134-
&'a SymbolTable,
135-
HashMap<&'a str, BitVecValue>,
136-
FxHashMap<StmtId, Option<StmtId>>,
137-
)> {
138-
if idx < todos.len() {
139-
// get the corresponding transaction and symbol table
140-
let ir_idx = todos[idx].0;
141-
let (tr, st) = irs[ir_idx];
142-
143-
// setup the arguments for the transaction
144-
let args = todos[idx].1.clone();
145-
let mut args_map = HashMap::new();
146-
147-
// setup the next_stmt_mapping from the parallel vector
148-
let next_stmt_mapping = next_stmt_mappings[ir_idx].clone();
149-
150-
for (i, arg) in args.iter().enumerate() {
151-
let identifier = st[tr.args[i].symbol()].name();
152-
args_map.insert(identifier, arg.clone());
153-
}
154-
155-
Some((tr, st, args_map, next_stmt_mapping))
156-
} else {
157-
None
158-
}
159-
}
160-
161175
pub fn execute_threads(&mut self) -> Vec<Result<(), String>> {
162176
println!(
163177
"\n==== Starting scheduling cycle {}, active threads: {} ====",
@@ -274,6 +288,7 @@ impl<'a> Scheduler<'a> {
274288
}
275289

276290
pub fn run_thread_until_next_step(&mut self, thread_idx: usize) {
291+
let next_todo_option = self.next_todo(self.next_todo_idx + 1);
277292
let thread = &mut self.active_threads[thread_idx];
278293
println!(
279294
"Running thread with transaction: {:?} from current_step: {:?}",
@@ -316,30 +331,25 @@ impl<'a> Scheduler<'a> {
316331
if self.evaluator.assertions_forks_enabled {
317332
// advance to the next todo index
318333
self.next_todo_idx += 1;
319-
if let Some((tr, st, args, next_stmt_map)) = Self::next_ir(
320-
&self.todos,
321-
self.next_todo_idx,
322-
self.irs.clone(),
323-
self.next_stmt_maps.clone(),
324-
) {
325-
println!(
326-
" Forking new thread with transaction: {:?}",
327-
tr.name
328-
);
329-
let next_thread = Thread::initialize_thread(
330-
tr,
331-
st,
332-
args,
333-
next_stmt_map,
334-
self.next_todo_idx,
335-
);
336-
self.next_threads.push(next_thread);
337-
println!(
338-
" Forked thread added to next_threads queue. Queue size: {}",
339-
self.next_threads.len()
340-
);
341-
} else {
342-
println!(" No more irs to fork, continuing execution");
334+
match next_todo_option.clone() {
335+
Some(todo) => {
336+
println!(
337+
" Forking new thread with transaction: {:?}",
338+
todo.tr.name
339+
);
340+
let next_thread = Thread::initialize_thread(
341+
todo,
342+
self.next_todo_idx,
343+
);
344+
self.next_threads.push(next_thread);
345+
println!(
346+
" Forked thread added to next_threads queue. Queue size: {}",
347+
self.next_threads.len()
348+
);
349+
}
350+
None => {
351+
println!(" No more irs to fork, continuing execution");
352+
}
343353
}
344354
} else {
345355
println!(" Fork encountered, but assertions_forks_enabled is false. Not forking.");
@@ -671,4 +681,4 @@ pub mod tests {
671681
let results = scheduler.execute_threads();
672682
assert!(results[0].is_err());
673683
}
674-
}
684+
}

0 commit comments

Comments
 (0)