@@ -18,6 +18,30 @@ use patronus::expr::Context;
1818use patronus:: sim:: Interpreter ;
1919use 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 ) ]
2246pub 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 thread’ s result)
53+ /// Index into the original `todos` (used to store this thread' s result)
3054 thread_id : usize ,
3155}
3256
3357impl < ' 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
7192impl < ' 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