about summary refs log blame commit diff stats
path: root/html/073wait.cc.html
blob: ffc27bb9eb41734592cd6e4ea5e31859bee701ac (plain) (tree)
1
2
3
4
5
6
7
8
9
10



                                                                                          
                              

                                                
                                  

                                                                                         

                       
                                                                                                 
                                                                                            

                                      
                             

                                  
                            

                              
                                  
                                                                           


                                   

        





                               

       
                         





                                                                                                          
                                      
                                                                                                               
                  


                                                                                                                           
                                                                                                                   
 
                                      
                                                                                                                          
 





                                                                         






                                                                                 
                                                                                   
                                                                            
                                                                                     
 



                                                                                                                                                                                                                                                     
                                




                                                                                                                                                                                 



                                                                                                                                                                                                      








                                                                                                                                                                                                                                                                                                                               





                                                                                                                                                                                                                                                                                                                               
 


                                                                                                         

                                                                                      
                                                       
                                                                                 
                                                                                                                                                                                                                                            
                                                                                
                                                                                          
                                                                                                                                                                                                                                                                                        
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               


                                                                                                                                                                                                                                                                                                                                   
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           
                                  

                                                                       
                                                                                         








                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      
                                                                                                    
                                                                                                              























                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         





                                                                                    
                                                                                                                                                                                                                                                                                                                             
                                                                                                                                                                                                                                                                                                          



                                                                                                                                                                                                                                                                                                                                                                                                                                               
                                                                                                                                                                   
                                                                                                                                                                                                         


                                  


                                                                                                   

                                                       
                                        

                                                                                                               
                                                                                                                                                                                                         









                                                                                                                                                                                                                                                                                        
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            

                                                                         
                                                                                                                                                                                                                                                                                                 
                                                                                                                                                                                                                          





                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           


                                                                                                                                            
                                                                                                                                                                                                                                           
                                                                                                                                                                                                                                                                           
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                





                                                                                                                                                                                                                                                                                                                                                                           
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               







                                                                                                                                                                                                                                                                                                                                
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             





                                                                                         
                                                                                                                                                                                                                                                                                                                  





                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   
                                                                                                                                                                                  
                                                                                                                                                                                                                                                                                          
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         

                                                                                                                                                                                                                                                       
                                                                                                                                                                                                             






                                                                                                                                                                                                                                                                                                                             
                                                                                                                                                                                                                                                        







                                                                                                                                                                                                                                                                                              
                                        


                                                                                                               
                                                                                                                                                                                                                                                                           
 
                                                                                    


                                                                       
                                        


                                                                                                               
                                                                                                                                                                     
 
                                                                                     


                                                                             
                                                

                                                                
 
                                        

                                                                                                                                           
                                                                                                                                                                                                                                    
 
                                                                                                                                               


                                                                             
                                        
                                                                                                              
                                                         

                                                                                                               
                                                                                                                                                                                                                    



                                                                  
                                        
                                                                                                              
                                                         


                                                                                                                           
                                                                                                                                                                                                                                 


                                                                  
                                                                       
 
                                                           
                                      
                                                          


                                                                                                 
                                                                                                            
                                                                                                                   
 
                                      
                                                                                                                                                           
                                                                                                                                 
                                                                                                               
 
                                      
                                                                                                     

                                                                                                              

                                                
                                                              
                                                


                                                                 
                                                

                                                                                                   


                                                                       
                                                                                  
                                                                            
                                                                                    

                                                                                      
                                                
                                                                                 
                                                                                                                                                                                                                              
                                                                                
                                                                                   
                                                                                                                                                                                                                                                                                        
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        


                                                                                                                                                                                                                                                                                                                                 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             




                                                                                         
                                                                                   




                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    


                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      



                                                                                    


                                                                                                        


                                                                                                                                                                                                                                                                                                                             

                                                                                                                                                                                                                                       


                                                                                                                                                                                                                                                                                                                               



                                                                                                                                                                                                                                                                                                                                                                           
                                                                                               
                                                                                                                                    



                                    












                                                                                                           
 












































                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               
                                      

                                                                                                   
                                                                                                     
                                                                                                                   
 
                                      
                                                                                                               
 
                                                
                                                                       
                                                
                                                                                              
                                                

                                                                                                   


                                                                       
                                                                                           
                                                                            
                                                                                             

                                                                                      
                                                         
                                                                                 
                                                                                                                                                                                                                                                
                                                                                
                                                                                            
                                                                                                                                                                                                                                                                                        
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 

                                                                         
                                                                                                                                                                                                                                                                                                                                 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      

                                                                         


                                                                                         
                                                                                            
                                                                                                                                                                                                                                                                                                                                                                                                                                         
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    

                                                                         
                                                                                                    

                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   



                                                                                    
                                                                                                
                                                                                                                                                                                                                                                                                                                             
                                                                                                                                                                                                                                                                                                          
                                                                                                                                

                                                                                                                                                                                                                                                
                                                                                                                                                                                         
                                                                                                                                                                                                                                                                                                                               
                                                                                                                                                                    


                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     
                                                                                               
                                                                                                                                             



                                    

                                                                                


                                                                                      

                                                                                                                                                                                                          
                                                                         

                                                                       

                                                                                                       
                                                                                         
                                                                         
                                                                                                   
                                                                                                                                    
                                                                                                                                      
                                                                                                      
                                                                                                                       


                                                                       
                                      

                                                                                                                                                                                                                                                                                                                               
                                                                                                                                                                                                      

                                                                                                                                                                                                                                                      
                                                                                                                                                                                                                                   



                                                                                                                                                                                               

























                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    
                                                                                                                                                                                                   







                                                                           
                                        
             

                                                                                                                                                                      

                                                                 
                                                                                                                                                                                                
 
                                     
                                                                                                                 

                                              


                                                                  
                                        
             
                                                                                                 




                                                                                                                       
                                     

                                                                                       








                                                                                                                                                                                


                                                                


       
                                     
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<title>Mu - 073wait.cc</title>
<meta name="Generator" content="Vim/7.4">
<meta name="plugin-version" content="vim7.4_v2">
<meta name="syntax" content="cpp">
<meta name="settings" content="use_css,pre_wrap,no_foldcolumn,expand_tabs,prevent_copy=">
<meta name="colorscheme" content="minimal">
<style type="text/css">
<!--
pre { white-space: pre-wrap; font-family: monospace; color: #eeeeee; background-color: #080808; }
body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color: #080808; }
* { font-size: 12pt; font-size: 1em; }
.Constant { color: #00a0a0; }
.cSpecial { color: #008000; }
.muRecipe { color: #ff8700; }
.CommentedCode { color: #6c6c6c; }
.Comment { color: #9090ff; }
.Delimiter { color: #800080; }
.Special { color: #c00000; }
.traceContains { color: #008000; }
.Normal { color: #eeeeee; background-color: #080808; padding-bottom: 1px; }
.muData { color: #ffff00; }
.Identifier { color: #fcb165; }
.SalientComment { color: #00ffff; }
-->
</style>

<script type='text/javascript'>
<!--

-->
</script>
</head>
<body>
<pre id='vimCodeElement'>
<span class="Comment">//: Routines can be put in a 'waiting' state, from which it will be ready to</span>
<span class="Comment">//: run again when a specific memory location changes its value. This is mu's</span>
<span class="Comment">//: basic technique for orchestrating the order in which different routines</span>
<span class="Comment">//: operate.</span>

<span class="Delimiter">:(scenario wait_for_location)</span>
<span class="muRecipe">def</span> f1 [
  <span class="Constant">10</span>:num<span class="Special"> &lt;- </span>copy <span class="Constant">34</span>
  start-running f2
  <span class="Constant">20</span>:location<span class="Special"> &lt;- </span>copy <span class="Constant">10</span>/unsafe
  wait-<span class="Normal">for</span>-reset-then-set <span class="Constant">20</span>:location
  <span class="Comment"># wait for f2 to run and reset location 1</span>
  <span class="Constant">30</span>:num<span class="Special"> &lt;- </span>copy <span class="Constant">10</span>:num
]
<span class="muRecipe">def</span> f2 [
  <span class="Constant">10</span>:location<span class="Special"> &lt;- </span>copy <span class="Constant">0</span>/unsafe
]
<span class="traceContains">+schedule: f1</span>
<span class="traceContains">+run: waiting for location 10 to reset</span>
<span class="traceContains">+schedule: f2</span>
<span class="traceContains">+schedule: waking up routine 1</span>
<span class="traceContains">+schedule: f1</span>
<span class="traceContains">+mem: storing 1 in location 30</span>

<span class="Comment">//: define the new state that all routines can be in</span>

<span class="Delimiter">:(before &quot;End routine States&quot;)</span>
WAITING<span class="Delimiter">,</span>
<span class="Delimiter">:(before &quot;End routine Fields&quot;)</span>
<span class="Comment">// only if state == WAITING</span>
<span class="Normal">int</span> waiting_on_location<span class="Delimiter">;</span>
<span class="Delimiter">:(before &quot;End routine Constructor&quot;)</span>
waiting_on_location = <span class="Constant">0</span><span class="Delimiter">;</span>

<span class="Delimiter">:(before &quot;End Mu Test Teardown&quot;)</span>
<span class="Normal">if</span> <span class="Delimiter">(</span>Passed &amp;&amp; any_routines_waiting<span class="Delimiter">())</span> <span class="Delimiter">{</span>
  Passed = <span class="Constant">false</span><span class="Delimiter">;</span>
  raise &lt;&lt; Current_scenario<span class="Delimiter">-&gt;</span>name &lt;&lt; <span class="Constant">&quot;: deadlock!</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span>
<span class="Delimiter">}</span>
<span class="Delimiter">:(before &quot;End Run Routine&quot;)</span>
<span class="Normal">if</span> <span class="Delimiter">(</span>any_routines_waiting<span class="Delimiter">())</span> <span class="Delimiter">{</span>
  raise &lt;&lt; <span class="Constant">&quot;deadlock!</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span>
  dump_waiting_routines<span class="Delimiter">();</span>
<span class="Delimiter">}</span>
<span class="Delimiter">:(before &quot;End Test Teardown&quot;)</span>
<span class="Normal">if</span> <span class="Delimiter">(</span>Passed &amp;&amp; any_routines_with_error<span class="Delimiter">())</span> <span class="Delimiter">{</span>
  Passed = <span class="Constant">false</span><span class="Delimiter">;</span>
  raise &lt;&lt; <span class="Constant">&quot;some routines died with errors</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span>
<span class="Delimiter">}</span>
<span class="Delimiter">:(code)</span>
<span class="Normal">bool</span> any_routines_waiting<span class="Delimiter">()</span> <span class="Delimiter">{</span>
  <span class="Normal">for</span> <span class="Delimiter">(</span><span class="Normal">int</span> i = <span class="Constant">0</span><span class="Delimiter">;</span> i &lt; SIZE<span class="Delimiter">(</span>Routines<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span>
    <span class="Normal">if</span> <span class="Delimiter">(</span>Routines<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">)-&gt;</span>state == WAITING<span class="Delimiter">)</span>
      <span class="Identifier">return</span> <span class="Constant">true</span><span class="Delimiter">;</span>
  <span class="Delimiter">}</span>
  <span class="Identifier">return</span> <span class="Constant">false</span><span class="Delimiter">;</span>
<span class="Delimiter">}</span>
<span class="Normal">void</span> dump_waiting_routines<span class="Delimiter">()</span> <span class="Delimiter">{</span>
  <span class="Normal">for</span> <span class="Delimiter">(</span><span class="Normal">int</span> i = <span class="Constant">0</span><span class="Delimiter">;</span> i &lt; SIZE<span class="Delimiter">(</span>Routines<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span>
    <span class="Normal">if</span> <span class="Delimiter">(</span>Routines<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">)-&gt;</span>state == WAITING<span class="Delimiter">)</span>
      cerr &lt;&lt; i &lt;&lt; <span class="Constant">&quot;: &quot;</span> &lt;&lt; routine_label<span class="Delimiter">(</span>Routines<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">))</span> &lt;&lt; <span class="cSpecial">'\n'</span><span class="Delimiter">;</span>
  <span class="Delimiter">}</span>
<span class="Delimiter">}</span>

<span class="Comment">//: Primitive recipe to put routines in that state.</span>
<span class="Comment">//: This primitive is also known elsewhere as compare-and-set (CAS). Used to</span>
<span class="Comment">//: build locks.</span>

<span class="Delimiter">:(before &quot;End Primitive Recipe Declarations&quot;)</span>
WAIT_FOR_RESET_THEN_SET<span class="Delimiter">,</span>
<span class="Delimiter">:(before &quot;End Primitive Recipe Numbers&quot;)</span>
put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> <span class="Constant">&quot;wait-for-reset-then-set&quot;</span><span class="Delimiter">,</span> WAIT_FOR_RESET_THEN_SET<span class="Delimiter">);</span>
<span class="Delimiter">:(before &quot;End Primitive Recipe Checks&quot;)</span>
<span class="Normal">case</span> WAIT_FOR_RESET_THEN_SET: <span class="Delimiter">{</span>
  <span class="Normal">if</span> <span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">)</span> != <span class="Constant">1</span><span class="Delimiter">)</span> <span class="Delimiter">{</span>
    raise &lt;&lt; maybe<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">).</span>name<span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;'wait-for-reset-then-set' requires exactly one ingredient, but got '&quot;</span> &lt;&lt; inst<span class="Delimiter">.</span>original_string &lt;&lt; <span class="Constant">&quot;'</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span>
    <span class="Identifier">break</span><span class="Delimiter">;</span>
  <span class="Delimiter">}</span>
  <span class="Normal">if</span> <span class="Delimiter">(</span>!is_mu_location<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">)))</span> <span class="Delimiter">{</span>
    raise &lt;&lt; maybe<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">).</span>name<span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;'wait-for-reset-then-set' requires a location ingredient, but got '&quot;</span> &lt;&lt; inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>original_string &lt;&lt; <span class="Constant">&quot;'</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span>
  <span class="Delimiter">}</span>
  <span class="Identifier">break</span><span class="Delimiter">;</span>
<span class="Delimiter">}</span>
<span class="Delimiter">:(before &quot;End Primitive Recipe Implementations&quot;)</span>
<span class="Normal">case</span> WAIT_FOR_RESET_THEN_SET: <span class="Delimiter">{</span>
  <span class="Normal">int</span> loc = <span class="Normal">static_cast</span>&lt;<span class="Normal">int</span>&gt;<span class="Delimiter">(</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">));</span>
  trace<span class="Delimiter">(</span><span class="Constant">9998</span><span class="Delimiter">,</span> <span class="Constant">&quot;run&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;wait: *&quot;</span> &lt;&lt; loc &lt;&lt; <span class="Constant">&quot; = &quot;</span> &lt;&lt; get_or_insert<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> loc<span class="Delimiter">)</span> &lt;&lt; end<span class="Delimiter">();</span>
  <span class="Normal">if</span> <span class="Delimiter">(</span>get_or_insert<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> loc<span class="Delimiter">)</span> == <span class="Constant">0</span><span class="Delimiter">)</span> <span class="Delimiter">{</span>
    trace<span class="Delimiter">(</span><span class="Constant">9998</span><span class="Delimiter">,</span> <span class="Constant">&quot;run&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;location &quot;</span> &lt;&lt; loc &lt;&lt; <span class="Constant">&quot; is already 0; setting&quot;</span> &lt;&lt; end<span class="Delimiter">();</span>
    put<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> loc<span class="Delimiter">,</span> <span class="Constant">1</span><span class="Delimiter">);</span>
    <span class="Identifier">break</span><span class="Delimiter">;</span>
  <span class="Delimiter">}</span>
  trace<span class="Delimiter">(</span><span class="Constant">9998</span><span class="Delimiter">,</span> <span class="Constant">&quot;run&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;waiting for location &quot;</span> &lt;&lt; loc &lt;&lt; <span class="Constant">&quot; to reset&quot;</span> &lt;&lt; end<span class="Delimiter">();</span>
  Current_routine<span class="Delimiter">-&gt;</span>state = WAITING<span class="Delimiter">;</span>
  Current_routine<span class="Delimiter">-&gt;</span>waiting_on_location = loc<span class="Delimiter">;</span>
  <span class="Identifier">break</span><span class="Delimiter">;</span>
<span class="Delimiter">}</span>

<span class="Comment">//: Counterpart to unlock a lock.</span>
<span class="Delimiter">:(before &quot;End Primitive Recipe Declarations&quot;)</span>
RESET<span class="Delimiter">,</span>
<span class="Delimiter">:(before &quot;End Primitive Recipe Numbers&quot;)</span>
put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> <span class="Constant">&quot;reset&quot;</span><span class="Delimiter">,</span> RESET<span class="Delimiter">);</span>
<span class="Delimiter">:(before &quot;End Primitive Recipe Checks&quot;)</span>
<span class="Normal">case</span> RESET: <span class="Delimiter">{</span>
  <span class="Normal">if</span> <span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">)</span> != <span class="Constant">1</span><span class="Delimiter">)</span> <span class="Delimiter">{</span>
    raise &lt;&lt; maybe<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">).</span>name<span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;'reset' requires exactly one ingredient, but got '&quot;</span> &lt;&lt; inst<span class="Delimiter">.</span>original_string &lt;&lt; <span class="Constant">&quot;'</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span>
    <span class="Identifier">break</span><span class="Delimiter">;</span>
  <span class="Delimiter">}</span>
  <span class="Normal">if</span> <span class="Delimiter">(</span>!is_mu_location<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">)))</span> <span class="Delimiter">{</span>
    raise &lt;&lt; maybe<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">).</span>name<span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;'reset' requires a location ingredient, but got '&quot;</span> &lt;&lt; inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>original_string &lt;&lt; <span class="Constant">&quot;'</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span>
  <span class="Delimiter">}</span>
  <span class="Identifier">break</span><span class="Delimiter">;</span>
<span class="Delimiter">}</span>
<span class="Delimiter">:(before &quot;End Primitive Recipe Implementations&quot;)</span>
<span class="Normal">case</span> RESET: <span class="Delimiter">{</span>
  <span class="Normal">int</span> loc = <span class="Normal">static_cast</span>&lt;<span class="Normal">int</span>&gt;<span class="Delimiter">(</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">));</span>
  put<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> loc<span class="Delimiter">,</span> <span class="Constant">0</span><span class="Delimiter">);</span>
  trace<span class="Delimiter">(</span><span class="Constant">9998</span><span class="Delimiter">,</span> <span class="Constant">&quot;run&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;reset: *&quot;</span> &lt;&lt; loc &lt;&lt; <span class="Constant">&quot; = &quot;</span> &lt;&lt; get_or_insert<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> loc<span class="Delimiter">)</span> &lt;&lt; end<span class="Delimiter">();</span>
  <span class="Identifier">break</span><span class="Delimiter">;</span>
<span class="Delimiter">}</span>

<span class="Comment">//: scheduler tweak to get routines out of that state</span>

<span class="Delimiter">:(before &quot;End Scheduler State Transitions&quot;)</span>
<span class="Normal">for</span> <span class="Delimiter">(</span><span class="Normal">int</span> i = <span class="Constant">0</span><span class="Delimiter">;</span> i &lt; SIZE<span class="Delimiter">(</span>Routines<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span>
  <span class="Normal">if</span> <span class="Delimiter">(</span>Routines<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">)-&gt;</span>state != WAITING<span class="Delimiter">)</span> <span class="Identifier">continue</span><span class="Delimiter">;</span>
  <span class="Normal">int</span> loc = Routines<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">)-&gt;</span>waiting_on_location<span class="Delimiter">;</span>
  <span class="Normal">if</span> <span class="Delimiter">(</span>loc &amp;&amp; get_or_insert<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> loc<span class="Delimiter">)</span> == <span class="Constant">0</span><span class="Delimiter">)</span> <span class="Delimiter">{</span>
    trace<span class="Delimiter">(</span><span class="Constant">9999</span><span class="Delimiter">,</span> <span class="Constant">&quot;schedule&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;waking up routine &quot;</span> &lt;&lt; Routines<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">)-&gt;</span>id &lt;&lt; end<span class="Delimiter">();</span>
    put<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> loc<span class="Delimiter">,</span> <span class="Constant">1</span><span class="Delimiter">);</span>
    Routines<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">)-&gt;</span>state = RUNNING<span class="Delimiter">;</span>
    Routines<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">)-&gt;</span>waiting_on_location = <span class="Constant">0</span><span class="Delimiter">;</span>
  <span class="Delimiter">}</span>
<span class="Delimiter">}</span>

<span class="Comment">//: Primitive to help compute locations to wait on.</span>
<span class="Comment">//: Only supports elements immediately inside containers; no arrays or</span>
<span class="Comment">//: containers within containers yet.</span>

<span class="Delimiter">:(scenario get_location)</span>
<span class="muRecipe">def</span> main [
  <span class="Constant">12</span>:num<span class="Special"> &lt;- </span>copy <span class="Constant">34</span>
  <span class="Constant">13</span>:num<span class="Special"> &lt;- </span>copy <span class="Constant">35</span>
  <span class="Constant">15</span>:location<span class="Special"> &lt;- </span>get-location <span class="Constant">12</span>:point<span class="Delimiter">,</span> <span class="Constant">1:offset</span>
]
<span class="traceContains">+mem: storing 13 in location 15</span>

<span class="Delimiter">:(before &quot;End Primitive Recipe Declarations&quot;)</span>
GET_LOCATION<span class="Delimiter">,</span>
<span class="Delimiter">:(before &quot;End Primitive Recipe Numbers&quot;)</span>
put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> <span class="Constant">&quot;get-location&quot;</span><span class="Delimiter">,</span> GET_LOCATION<span class="Delimiter">);</span>
<span class="Delimiter">:(before &quot;End Primitive Recipe Checks&quot;)</span>
<span class="Normal">case</span> GET_LOCATION: <span class="Delimiter">{</span>
  <span class="Normal">if</span> <span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">)</span> != <span class="Constant">2</span><span class="Delimiter">)</span> <span class="Delimiter">{</span>
    raise &lt;&lt; maybe<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">).</span>name<span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;'get-location' expects exactly 2 ingredients in '&quot;</span> &lt;&lt; inst<span class="Delimiter">.</span>original_string &lt;&lt; <span class="Constant">&quot;'</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span>
    <span class="Identifier">break</span><span class="Delimiter">;</span>
  <span class="Delimiter">}</span>
  reagent<span class="Comment">/*</span><span class="Comment">copy</span><span class="Comment">*/</span> base = inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">);</span>
  <span class="Normal">if</span> <span class="Delimiter">(</span>!canonize_type<span class="Delimiter">(</span>base<span class="Delimiter">))</span> <span class="Identifier">break</span><span class="Delimiter">;</span>
  <span class="Normal">if</span> <span class="Delimiter">(</span>!base<span class="Delimiter">.</span>type<span class="Delimiter">)</span> <span class="Delimiter">{</span>
    raise &lt;&lt; maybe<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">).</span>name<span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;first ingredient of 'get-location' should be a container, but got '&quot;</span> &lt;&lt; inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>original_string &lt;&lt; <span class="Constant">&quot;'</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span>
    <span class="Identifier">break</span><span class="Delimiter">;</span>
  <span class="Delimiter">}</span>
  <span class="Normal">const</span> type_tree* base_root_type = base<span class="Delimiter">.</span>type<span class="Delimiter">-&gt;</span>atom ? base<span class="Delimiter">.</span>type : base<span class="Delimiter">.</span>type<span class="Delimiter">-&gt;</span>left<span class="Delimiter">;</span>
  <span class="Normal">if</span> <span class="Delimiter">(</span>!base_root_type<span class="Delimiter">-&gt;</span>atom || base_root_type<span class="Delimiter">-&gt;</span>value == <span class="Constant">0</span> || !contains_key<span class="Delimiter">(</span>Type<span class="Delimiter">,</span> base_root_type<span class="Delimiter">-&gt;</span>value<span class="Delimiter">)</span> || get<span class="Delimiter">(</span>Type<span class="Delimiter">,</span> base_root_type<span class="Delimiter">-&gt;</span>value<span class="Delimiter">).</span>kind != CONTAINER<span class="Delimiter">)</span> <span class="Delimiter">{</span>
    raise &lt;&lt; maybe<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">).</span>name<span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;first ingredient of 'get-location' should be a container, but got '&quot;</span> &lt;&lt; inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>original_string &lt;&lt; <span class="Constant">&quot;'</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span>
    <span class="Identifier">break</span><span class="Delimiter">;</span>
  <span class="Delimiter">}</span>
  type_ordinal base_type = base<span class="Delimiter">.</span>type<span class="Delimiter">-&gt;</span>value<span class="Delimiter">;</span>
  <span class="Normal">const</span> reagent&amp; offset = inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">);</span>
  <span class="Normal">if</span> <span class="Delimiter">(</span>!is_literal<span class="Delimiter">(</span>offset<span class="Delimiter">)</span> || !is_mu_scalar<span class="Delimiter">(</span>offset<span class="Delimiter">))</span> <span class="Delimiter">{</span>
    raise &lt;&lt; maybe<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">).</span>name<span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;second ingredient of 'get-location' should have type 'offset', but got '&quot;</span> &lt;&lt; inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">).</span>original_string &lt;&lt; <span class="Constant">&quot;'</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span>
    <span class="Identifier">break</span><span class="Delimiter">;</span>
  <span class="Delimiter">}</span>
  <span class="Normal">int</span> offset_value = <span class="Constant">0</span><span class="Delimiter">;</span>
  <span class="Normal">if</span> <span class="Delimiter">(</span>is_integer<span class="Delimiter">(</span>offset<span class="Delimiter">.</span>name<span class="Delimiter">))</span> <span class="Delimiter">{</span>  <span class="Comment">// later layers permit non-integer offsets</span>
    offset_value = to_integer<span class="Delimiter">(</span>offset<span class="Delimiter">.</span>name<span class="Delimiter">);</span>
    <span class="Normal">if</span> <span class="Delimiter">(</span>offset_value &lt; <span class="Constant">0</span> || offset_value &gt;= SIZE<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Type<span class="Delimiter">,</span> base_type<span class="Delimiter">).</span>elements<span class="Delimiter">))</span> <span class="Delimiter">{</span>
      raise &lt;&lt; maybe<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">).</span>name<span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;invalid offset &quot;</span> &lt;&lt; offset_value &lt;&lt; <span class="Constant">&quot; for '&quot;</span> &lt;&lt; get<span class="Delimiter">(</span>Type<span class="Delimiter">,</span> base_type<span class="Delimiter">).</span>name &lt;&lt; <span class="Constant">&quot;'</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span>
      <span class="Identifier">break</span><span class="Delimiter">;</span>
    <span class="Delimiter">}</span>
  <span class="Delimiter">}</span>
  <span class="Normal">else</span> <span class="Delimiter">{</span>
    offset_value = offset<span class="Delimiter">.</span>value<span class="Delimiter">;</span>
  <span class="Delimiter">}</span>
  <span class="Normal">if</span> <span class="Delimiter">(</span>inst<span class="Delimiter">.</span>products<span class="Delimiter">.</span>empty<span class="Delimiter">())</span> <span class="Identifier">break</span><span class="Delimiter">;</span>
  <span class="Normal">if</span> <span class="Delimiter">(</span>!is_mu_location<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">)))</span> <span class="Delimiter">{</span>
    raise &lt;&lt; maybe<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">).</span>name<span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;'get-location &quot;</span> &lt;&lt; base<span class="Delimiter">.</span>original_string &lt;&lt; <span class="Constant">&quot;, &quot;</span> &lt;&lt; offset<span class="Delimiter">.</span>original_string &lt;&lt; <span class="Constant">&quot;' should write to type location but '&quot;</span> &lt;&lt; inst<span class="Delimiter">.</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>name &lt;&lt; <span class="Constant">&quot;' has type '&quot;</span> &lt;&lt; names_to_string_without_quotes<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>type<span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;'</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span>
    <span class="Identifier">break</span><span class="Delimiter">;</span>
  <span class="Delimiter">}</span>
  <span class="Identifier">break</span><span class="Delimiter">;</span>
<span class="Delimiter">}</span>
<span class="Delimiter">:(before &quot;End Primitive Recipe Implementations&quot;)</span>
<span class="Normal">case</span> GET_LOCATION: <span class="Delimiter">{</span>
  reagent<span class="Comment">/*</span><span class="Comment">copy</span><span class="Comment">*/</span> base = current_instruction<span class="Delimiter">().</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">);</span>
  canonize<span class="Delimiter">(</span>base<span class="Delimiter">);</span>
  <span class="Normal">int</span> base_address = base<span class="Delimiter">.</span>value<span class="Delimiter">;</span>
  <span class="Normal">if</span> <span class="Delimiter">(</span>base_address == <span class="Constant">0</span><span class="Delimiter">)</span> <span class="Delimiter">{</span>
    raise &lt;&lt; maybe<span class="Delimiter">(</span>current_recipe_name<span class="Delimiter">())</span> &lt;&lt; <span class="Constant">&quot;tried to access location 0 in '&quot;</span> &lt;&lt; to_original_string<span class="Delimiter">(</span>current_instruction<span class="Delimiter">())</span> &lt;&lt; <span class="Constant">&quot;'</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span>
    <span class="Identifier">break</span><span class="Delimiter">;</span>
  <span class="Delimiter">}</span>
  <span class="Normal">const</span> type_tree* base_root_type = root_type<span class="Delimiter">(</span>base<span class="Delimiter">.</span>type<span class="Delimiter">);</span>
  <span class="Normal">int</span> offset = ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">).</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">);</span>
  <span class="Normal">if</span> <span class="Delimiter">(</span>offset &lt; <span class="Constant">0</span> || offset &gt;= SIZE<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Type<span class="Delimiter">,</span> base_root_type<span class="Delimiter">-&gt;</span>value<span class="Delimiter">).</span>elements<span class="Delimiter">))</span> <span class="Identifier">break</span><span class="Delimiter">;</span>  <span class="Comment">// copied from Check above</span>
  <span class="Normal">int</span> result = base_address<span class="Delimiter">;</span>
  <span class="Normal">for</span> <span class="Delimiter">(</span><span class="Normal">int</span> i = <span class="Constant">0</span><span class="Delimiter">;</span> i &lt; offset<span class="Delimiter">;</span> ++i<span class="Delimiter">)</span>
    result += size_of<span class="Delimiter">(</span>element_type<span class="Delimiter">(</span>base<span class="Delimiter">.</span>type<span class="Delimiter">,</span> i<span class="Delimiter">));</span>
  trace<span class="Delimiter">(</span><span class="Constant">9998</span><span class="Delimiter">,</span> <span class="Constant">&quot;run&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;address to copy is &quot;</span> &lt;&lt; result &lt;&lt; end<span class="Delimiter">();</span>
  products<span class="Delimiter">.</span>resize<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">);</span>
  products<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>push_back<span class="Delimiter">(</span>result<span class="Delimiter">);</span>
  <span class="Identifier">break</span><span class="Delimiter">;</span>
<span class="Delimiter">}</span>

<span class="Delimiter">:(code)</span>
<span class="Normal">bool</span> is_mu_location<span class="Delimiter">(</span>reagent<span class="Comment">/*</span><span class="Comment">copy</span><span class="Comment">*/</span> x<span class="Delimiter">)</span> <span class="Delimiter">{</span>
  <span class="Normal">if</span> <span class="Delimiter">(</span>!canonize_type<span class="Delimiter">(</span>x<span class="Delimiter">))</span> <span class="Identifier">return</span> <span class="Constant">false</span><span class="Delimiter">;</span>
  <span class="Normal">if</span> <span class="Delimiter">(</span>!x<span class="Delimiter">.</span>type<span class="Delimiter">)</span> <span class="Identifier">return</span> <span class="Constant">false</span><span class="Delimiter">;</span>
  <span class="Normal">if</span> <span class="Delimiter">(</span>x<span class="Delimiter">.</span>type<span class="Delimiter">-&gt;</span>right<span class="Delimiter">)</span> <span class="Identifier">return</span> <span class="Constant">false</span><span class="Delimiter">;</span>
  <span class="Identifier">return</span> x<span class="Delimiter">.</span>type<span class="Delimiter">-&gt;</span>value == get<span class="Delimiter">(</span>Type_ordinal<span class="Delimiter">,</span> <span class="Constant">&quot;location&quot;</span><span class="Delimiter">);</span>
<span class="Delimiter">}</span>

<span class="Delimiter">:(scenario get_location_out_of_bounds)</span>
<span class="Special">% Hide_errors = true;</span>
<span class="muRecipe">def</span> main [
  <span class="Constant">12</span>:num<span class="Special"> &lt;- </span>copy <span class="Constant">34</span>
  <span class="Constant">13</span>:num<span class="Special"> &lt;- </span>copy <span class="Constant">35</span>
  <span class="Constant">14</span>:num<span class="Special"> &lt;- </span>copy <span class="Constant">36</span>
  get-location <span class="Constant">12</span>:point-number/<span class="Special">raw</span><span class="Delimiter">,</span> <span class="Constant">2:offset</span>  <span class="Comment"># point-number occupies 3 locations but has only 2 fields; out of bounds</span>
]
<span class="traceContains">+error: main: invalid offset 2 for 'point-number'</span>

<span class="Delimiter">:(scenario get_location_out_of_bounds_2)</span>
<span class="Special">% Hide_errors = true;</span>
<span class="muRecipe">def</span> main [
  <span class="Constant">12</span>:num<span class="Special"> &lt;- </span>copy <span class="Constant">34</span>
  <span class="Constant">13</span>:num<span class="Special"> &lt;- </span>copy <span class="Constant">35</span>
  <span class="Constant">14</span>:num<span class="Special"> &lt;- </span>copy <span class="Constant">36</span>
  get-location <span class="Constant">12</span>:point-number/<span class="Special">raw</span><span class="Delimiter">,</span> <span class="Constant">-1:offset</span>
]
<span class="traceContains">+error: main: invalid offset -1 for 'point-number'</span>

<span class="Delimiter">:(scenario get_location_product_type_mismatch)</span>
<span class="Special">% Hide_errors = true;</span>
<span class="muData">container</span> boolbool [
  <span class="Normal">x</span>:<span class="Normal">bool</span>
  <span class="Normal">y</span>:<span class="Normal">bool</span>
]
<span class="muRecipe">def</span> main [
  <span class="Constant">12</span>:<span class="Normal">bool</span><span class="Special"> &lt;- </span>copy <span class="Constant">1</span>
  <span class="Constant">13</span>:<span class="Normal">bool</span><span class="Special"> &lt;- </span>copy <span class="Constant">0</span>
  <span class="Constant">15</span>:<span class="Normal">bool</span><span class="Special"> &lt;- </span>get-location <span class="Constant">12</span>:boolbool<span class="Delimiter">,</span> <span class="Constant">1:offset</span>
]
<span class="traceContains">+error: main: 'get-location 12:boolbool, 1:offset' should write to type location but '15' has type 'boolean'</span>

<span class="Delimiter">:(scenario get_location_indirect)</span>
<span class="Comment"># 'get-location' can read from container address</span>
<span class="muRecipe">def</span> main [
  <span class="Constant">1</span>:num<span class="Special"> &lt;- </span>copy <span class="Constant">10</span>
  <span class="Comment"># 10 reserved for refcount</span>
  <span class="Constant">11</span>:num<span class="Special"> &lt;- </span>copy <span class="Constant">34</span>
  <span class="Constant">12</span>:num<span class="Special"> &lt;- </span>copy <span class="Constant">35</span>
  <span class="Constant">4</span>:location<span class="Special"> &lt;- </span>get-location <span class="Constant">1</span>:&amp;:point/lookup<span class="Delimiter">,</span> <span class="Constant">0:offset</span>
]
<span class="traceContains">+mem: storing 11 in location 4</span>

<span class="Delimiter">:(scenario get_location_indirect_2)</span>
<span class="muRecipe">def</span> main [
  <span class="Constant">1</span>:num<span class="Special"> &lt;- </span>copy <span class="Constant">10</span>
  <span class="Comment"># 10 reserved for refcount</span>
  <span class="Constant">11</span>:num<span class="Special"> &lt;- </span>copy <span class="Constant">34</span>
  <span class="Constant">12</span>:num<span class="Special"> &lt;- </span>copy <span class="Constant">35</span>
  <span class="Constant">4</span>:&amp;:num<span class="Special"> &lt;- </span>copy <span class="Constant">20</span>/unsafe
  <span class="Constant">4</span>:&amp;:location/lookup<span class="Special"> &lt;- </span>get-location <span class="Constant">1</span>:&amp;:point/lookup<span class="Delimiter">,</span> <span class="Constant">0:offset</span>
]
<span class="traceContains">+mem: storing 11 in location 21</span>

<span class="Comment">//: allow waiting on a routine to complete</span>

<span class="Delimiter">:(scenario wait_for_routine)</span>
<span class="muRecipe">def</span> f1 [
  <span class="Comment"># add a few routines to run</span>
  <span class="Constant">1</span>:num/routine<span class="Special"> &lt;- </span>start-running f2
  <span class="Constant">2</span>:num/routine<span class="Special"> &lt;- </span>start-running f3
  wait-<span class="Normal">for</span>-routine <span class="Constant">1</span>:num/routine
  <span class="Comment"># now wait for f2 to *complete* and modify location 13 before using its value</span>
  <span class="Constant">20</span>:num<span class="Special"> &lt;- </span>copy <span class="Constant">13</span>:num
]
<span class="muRecipe">def</span> f2 [
  <span class="Constant">10</span>:num<span class="Special"> &lt;- </span>copy <span class="Constant">0</span>  <span class="Comment"># just padding</span>
  <span class="Normal">switch</span>  <span class="Comment"># simulate a block; routine f1 shouldn't restart at this point</span>
  <span class="Constant">13</span>:num<span class="Special"> &lt;- </span>copy <span class="Constant">34</span>
]
<span class="muRecipe">def</span> f3 [
  <span class="Comment"># padding routine just to help simulate the block in f2 using 'switch'</span>
  <span class="Constant">11</span>:num<span class="Special"> &lt;- </span>copy <span class="Constant">0</span>
  <span class="Constant">12</span>:num<span class="Special"> &lt;- </span>copy <span class="Constant">0</span>
]
<span class="traceContains">+schedule: f1</span>
<span class="traceContains">+run: waiting for routine 2</span>
<span class="traceContains">+schedule: f2</span>
<span class="traceContains">+schedule: f3</span>
<span class="traceContains">+schedule: f2</span>
<span class="traceContains">+schedule: waking up routine 1</span>
<span class="traceContains">+schedule: f1</span>
<span class="Comment"># if we got the synchronization wrong we'd be storing 0 in location 20</span>
<span class="traceContains">+mem: storing 34 in location 20</span>

<span class="Delimiter">:(before &quot;End routine Fields&quot;)</span>
<span class="Comment">// only if state == WAITING</span>
<span class="Normal">int</span> waiting_on_routine<span class="Delimiter">;</span>
<span class="Delimiter">:(before &quot;End routine Constructor&quot;)</span>
waiting_on_routine = <span class="Constant">0</span><span class="Delimiter">;</span>

<span class="Delimiter">:(before &quot;End Primitive Recipe Declarations&quot;)</span>
WAIT_FOR_ROUTINE<span class="Delimiter">,</span>
<span class="Delimiter">:(before &quot;End Primitive Recipe Numbers&quot;)</span>
put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> <span class="Constant">&quot;wait-for-routine&quot;</span><span class="Delimiter">,</span> WAIT_FOR_ROUTINE<span class="Delimiter">);</span>
<span class="Delimiter">:(before &quot;End Primitive Recipe Checks&quot;)</span>
<span class="Normal">case</span> WAIT_FOR_ROUTINE: <span class="Delimiter">{</span>
  <span class="Normal">if</span> <span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">)</span> != <span class="Constant">1</span><span class="Delimiter">)</span> <span class="Delimiter">{</span>
    raise &lt;&lt; maybe<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">).</span>name<span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;'wait-for-routine' requires exactly one ingredient, but got '&quot;</span> &lt;&lt; inst<span class="Delimiter">.</span>original_string &lt;&lt; <span class="Constant">&quot;'</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span>
    <span class="Identifier">break</span><span class="Delimiter">;</span>
  <span class="Delimiter">}</span>
  <span class="Normal">if</span> <span class="Delimiter">(</span>!is_mu_number<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">)))</span> <span class="Delimiter">{</span>
    raise &lt;&lt; maybe<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">).</span>name<span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;first ingredient of 'wait-for-routine' should be a routine id generated by 'start-running', but got '&quot;</span> &lt;&lt; inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>original_string &lt;&lt; <span class="Constant">&quot;'</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span>
    <span class="Identifier">break</span><span class="Delimiter">;</span>
  <span class="Delimiter">}</span>
  <span class="Identifier">break</span><span class="Delimiter">;</span>
<span class="Delimiter">}</span>
<span class="Delimiter">:(before &quot;End Primitive Recipe Implementations&quot;)</span>
<span class="Normal">case</span> WAIT_FOR_ROUTINE: <span class="Delimiter">{</span>
  <span class="Normal">if</span> <span class="Delimiter">(</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">)</span> == Current_routine<span class="Delimiter">-&gt;</span>id<span class="Delimiter">)</span> <span class="Delimiter">{</span>
    raise &lt;&lt; maybe<span class="Delimiter">(</span>current_recipe_name<span class="Delimiter">())</span> &lt;&lt; <span class="Constant">&quot;routine can't wait for itself! '&quot;</span> &lt;&lt; to_original_string<span class="Delimiter">(</span>current_instruction<span class="Delimiter">())</span> &lt;&lt; <span class="Constant">&quot;'</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span>
    <span class="Identifier">break</span><span class="Delimiter">;</span>
  <span class="Delimiter">}</span>
  Current_routine<span class="Delimiter">-&gt;</span>state = WAITING<span class="Delimiter">;</span>
  Current_routine<span class="Delimiter">-&gt;</span>waiting_on_routine = ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">);</span>
  trace<span class="Delimiter">(</span><span class="Constant">9998</span><span class="Delimiter">,</span> <span class="Constant">&quot;run&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;waiting for routine &quot;</span> &lt;&lt; ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">)</span> &lt;&lt; end<span class="Delimiter">();</span>
<span class="CommentedCode">//?   cerr &lt;&lt; Current_routine-&gt;id &lt;&lt; &quot;: waiting for routine &quot; &lt;&lt; ingredients.at(0).at(0) &lt;&lt; '\n';</span>
  <span class="Identifier">break</span><span class="Delimiter">;</span>
<span class="Delimiter">}</span>

<span class="Delimiter">:(before &quot;End Scheduler State Transitions&quot;)</span>
<span class="Comment">// Wake up any routines waiting for other routines to complete.</span>
<span class="Comment">// Important: this must come after the scheduler loop above giving routines</span>
<span class="Comment">// waiting for locations to change a chance to wake up.</span>
<span class="Normal">for</span> <span class="Delimiter">(</span><span class="Normal">int</span> i = <span class="Constant">0</span><span class="Delimiter">;</span> i &lt; SIZE<span class="Delimiter">(</span>Routines<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span>
  <span class="Normal">if</span> <span class="Delimiter">(</span>Routines<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">)-&gt;</span>state != WAITING<span class="Delimiter">)</span> <span class="Identifier">continue</span><span class="Delimiter">;</span>
  routine* waiter = Routines<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">);</span>
  <span class="Normal">if</span> <span class="Delimiter">(</span>!waiter<span class="Delimiter">-&gt;</span>waiting_on_routine<span class="Delimiter">)</span> <span class="Identifier">continue</span><span class="Delimiter">;</span>
  <span class="Normal">int</span> id = waiter<span class="Delimiter">-&gt;</span>waiting_on_routine<span class="Delimiter">;</span>
  assert<span class="Delimiter">(</span>id != waiter<span class="Delimiter">-&gt;</span>id<span class="Delimiter">);</span>  <span class="Comment">// routine can't wait on itself</span>
  <span class="Normal">for</span> <span class="Delimiter">(</span><span class="Normal">int</span> j = <span class="Constant">0</span><span class="Delimiter">;</span> j &lt; SIZE<span class="Delimiter">(</span>Routines<span class="Delimiter">);</span> ++j<span class="Delimiter">)</span> <span class="Delimiter">{</span>
    <span class="Normal">const</span> routine* waitee = Routines<span class="Delimiter">.</span>at<span class="Delimiter">(</span>j<span class="Delimiter">);</span>
    <span class="Normal">if</span> <span class="Delimiter">(</span>waitee<span class="Delimiter">-&gt;</span>id == id &amp;&amp; waitee<span class="Delimiter">-&gt;</span>state != RUNNING &amp;&amp; waitee<span class="Delimiter">-&gt;</span>state != WAITING<span class="Delimiter">)</span> <span class="Delimiter">{</span>
      <span class="Comment">// routine is COMPLETED or DISCONTINUED</span>
      trace<span class="Delimiter">(</span><span class="Constant">9999</span><span class="Delimiter">,</span> <span class="Constant">&quot;schedule&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;waking up routine &quot;</span> &lt;&lt; waiter<span class="Delimiter">-&gt;</span>id &lt;&lt; end<span class="Delimiter">();</span>
<span class="CommentedCode">//?       cerr &lt;&lt; id &lt;&lt; &quot; is now done (&quot; &lt;&lt; waitee-&gt;state &lt;&lt; &quot;); waking up waiting routine &quot; &lt;&lt; waiter-&gt;id &lt;&lt; '\n';</span>
      waiter<span class="Delimiter">-&gt;</span>state = RUNNING<span class="Delimiter">;</span>
      waiter<span class="Delimiter">-&gt;</span>waiting_on_routine = <span class="Constant">0</span><span class="Delimiter">;</span>
    <span class="Delimiter">}</span>
  <span class="Delimiter">}</span>
<span class="Delimiter">}</span>

<span class="SalientComment">//:: helpers for manipulating routines in tests</span>
<span class="Comment">//:</span>
<span class="Comment">//: Managing arbitrary scenarios requires the ability to:</span>
<span class="Comment">//:   a) stop the current routine (`switch`)</span>
<span class="Comment">//:   b) restart a routine (`restart`)</span>
<span class="Comment">//:   c) tell when a routine is blocked</span>
<span class="Comment">//:</span>
<span class="Comment">//: A routine is blocked either if it's waiting or if it explicitly signals</span>
<span class="Comment">//: that it's blocked (even as it periodically wakes up and polls for some</span>
<span class="Comment">//: event).</span>
<span class="Comment">//:</span>
<span class="Comment">//: Signalling blockedness might well be a huge hack. But Mu doesn't have Unix</span>
<span class="Comment">//: signals to avoid polling with, because signals are also pretty hacky.</span>

<span class="Delimiter">:(before &quot;End routine Fields&quot;)</span>
<span class="Normal">bool</span> blocked<span class="Delimiter">;</span>
<span class="Delimiter">:(before &quot;End routine Constructor&quot;)</span>
blocked = <span class="Constant">false</span><span class="Delimiter">;</span>

<span class="Delimiter">:(before &quot;End Primitive Recipe Declarations&quot;)</span>
CURRENT_ROUTINE_IS_BLOCKED<span class="Delimiter">,</span>
<span class="Delimiter">:(before &quot;End Primitive Recipe Numbers&quot;)</span>
put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> <span class="Constant">&quot;current-routine-is-blocked&quot;</span><span class="Delimiter">,</span> CURRENT_ROUTINE_IS_BLOCKED<span class="Delimiter">);</span>
<span class="Delimiter">:(before &quot;End Primitive Recipe Checks&quot;)</span>
<span class="Normal">case</span> CURRENT_ROUTINE_IS_BLOCKED: <span class="Delimiter">{</span>
  <span class="Normal">if</span> <span class="Delimiter">(</span>!inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>empty<span class="Delimiter">())</span> <span class="Delimiter">{</span>
    raise &lt;&lt; maybe<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">).</span>name<span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;'current-routine-is-blocked' should have no ingredients, but got '&quot;</span> &lt;&lt; inst<span class="Delimiter">.</span>original_string &lt;&lt; <span class="Constant">&quot;'</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span>
    <span class="Identifier">break</span><span class="Delimiter">;</span>
  <span class="Delimiter">}</span>
  <span class="Identifier">break</span><span class="Delimiter">;</span>
<span class="Delimiter">}</span>
<span class="Delimiter">:(before &quot;End Primitive Recipe Implementations&quot;)</span>
<span class="Normal">case</span> CURRENT_ROUTINE_IS_BLOCKED: <span class="Delimiter">{</span>
  Current_routine<span class="Delimiter">-&gt;</span>blocked = <span class="Constant">true</span><span class="Delimiter">;</span>
  <span class="Identifier">break</span><span class="Delimiter">;</span>
<span class="Delimiter">}</span>

<span class="Delimiter">:(before &quot;End Primitive Recipe Declarations&quot;)</span>
CURRENT_ROUTINE_IS_UNBLOCKED<span class="Delimiter">,</span>
<span class="Delimiter">:(before &quot;End Primitive Recipe Numbers&quot;)</span>
put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> <span class="Constant">&quot;current-routine-is-unblocked&quot;</span><span class="Delimiter">,</span> CURRENT_ROUTINE_IS_UNBLOCKED<span class="Delimiter">);</span>
<span class="Delimiter">:(before &quot;End Primitive Recipe Checks&quot;)</span>
<span class="Normal">case</span> CURRENT_ROUTINE_IS_UNBLOCKED: <span class="Delimiter">{</span>
  <span class="Normal">if</span> <span class="Delimiter">(</span>!inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>empty<span class="Delimiter">())</span> <span class="Delimiter">{</span>
    raise &lt;&lt; maybe<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">).</span>name<span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;'current-routine-is-unblocked' should have no ingredients, but got '&quot;</span> &lt;&lt; inst<span class="Delimiter">.</span>original_string &lt;&lt; <span class="Constant">&quot;'</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span>
    <span class="Identifier">break</span><span class="Delimiter">;</span>
  <span class="Delimiter">}</span>
  <span class="Identifier">break</span><span class="Delimiter">;</span>
<span class="Delimiter">}</span>
<span class="Delimiter">:(before &quot;End Primitive Recipe Implementations&quot;)</span>
<span class="Normal">case</span> CURRENT_ROUTINE_IS_UNBLOCKED: <span class="Delimiter">{</span>
  Current_routine<span class="Delimiter">-&gt;</span>blocked = <span class="Constant">false</span><span class="Delimiter">;</span>
  <span class="Identifier">break</span><span class="Delimiter">;</span>
<span class="Delimiter">}</span>

<span class="Comment">//: also allow waiting on a routine to block</span>
<span class="Comment">//: (just for tests; use wait_for_routine above wherever possible)</span>

<span class="Delimiter">:(scenario wait_for_routine_to_block)</span>
<span class="muRecipe">def</span> f1 [
  <span class="Constant">1</span>:num/routine<span class="Special"> &lt;- </span>start-running f2
  wait-<span class="Normal">for</span>-routine-to-block <span class="Constant">1</span>:num/routine
  <span class="Comment"># now wait for f2 to run and modify location 10 before using its value</span>
  <span class="Constant">11</span>:num<span class="Special"> &lt;- </span>copy <span class="Constant">10</span>:num
]
<span class="muRecipe">def</span> f2 [
  <span class="Constant">10</span>:num<span class="Special"> &lt;- </span>copy <span class="Constant">34</span>
]
<span class="traceContains">+schedule: f1</span>
<span class="traceContains">+run: waiting for routine 2 to block</span>
<span class="traceContains">+schedule: f2</span>
<span class="traceContains">+schedule: waking up routine 1 because routine 2 is blocked</span>
<span class="traceContains">+schedule: f1</span>
<span class="Comment"># if we got the synchronization wrong we'd be storing 0 in location 11</span>
<span class="traceContains">+mem: storing 34 in location 11</span>

<span class="Delimiter">:(before &quot;End routine Fields&quot;)</span>
<span class="Comment">// only if state == WAITING</span>
<span class="Normal">int</span> waiting_on_routine_to_block<span class="Delimiter">;</span>
<span class="Delimiter">:(before &quot;End routine Constructor&quot;)</span>
waiting_on_routine_to_block = <span class="Constant">0</span><span class="Delimiter">;</span>

<span class="Delimiter">:(before &quot;End Primitive Recipe Declarations&quot;)</span>
WAIT_FOR_ROUTINE_TO_BLOCK<span class="Delimiter">,</span>
<span class="Delimiter">:(before &quot;End Primitive Recipe Numbers&quot;)</span>
put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> <span class="Constant">&quot;wait-for-routine-to-block&quot;</span><span class="Delimiter">,</span> WAIT_FOR_ROUTINE_TO_BLOCK<span class="Delimiter">);</span>
<span class="Delimiter">:(before &quot;End Primitive Recipe Checks&quot;)</span>
<span class="Normal">case</span> WAIT_FOR_ROUTINE_TO_BLOCK: <span class="Delimiter">{</span>
  <span class="Normal">if</span> <span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">)</span> != <span class="Constant">1</span><span class="Delimiter">)</span> <span class="Delimiter">{</span>
    raise &lt;&lt; maybe<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">).</span>name<span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;'wait-for-routine-to-block' requires exactly one ingredient, but got '&quot;</span> &lt;&lt; inst<span class="Delimiter">.</span>original_string &lt;&lt; <span class="Constant">&quot;'</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span>
    <span class="Identifier">break</span><span class="Delimiter">;</span>
  <span class="Delimiter">}</span>
  <span class="Normal">if</span> <span class="Delimiter">(</span>!is_mu_number<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">)))</span> <span class="Delimiter">{</span>
    raise &lt;&lt; maybe<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">).</span>name<span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;first ingredient of 'wait-for-routine-to-block' should be a routine id generated by 'start-running', but got '&quot;</span> &lt;&lt; inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>original_string &lt;&lt; <span class="Constant">&quot;'</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span>
    <span class="Identifier">break</span><span class="Delimiter">;</span>
  <span class="Delimiter">}</span>
  <span class="Identifier">break</span><span class="Delimiter">;</span>
<span class="Delimiter">}</span>
<span class="Delimiter">:(before &quot;End Primitive Recipe Implementations&quot;)</span>
<span class="Normal">case</span> WAIT_FOR_ROUTINE_TO_BLOCK: <span class="Delimiter">{</span>
  <span class="Normal">if</span> <span class="Delimiter">(</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">)</span> == Current_routine<span class="Delimiter">-&gt;</span>id<span class="Delimiter">)</span> <span class="Delimiter">{</span>
    raise &lt;&lt; maybe<span class="Delimiter">(</span>current_recipe_name<span class="Delimiter">())</span> &lt;&lt; <span class="Constant">&quot;routine can't wait for itself! '&quot;</span> &lt;&lt; to_original_string<span class="Delimiter">(</span>current_instruction<span class="Delimiter">())</span> &lt;&lt; <span class="Constant">&quot;'</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span>
    <span class="Identifier">break</span><span class="Delimiter">;</span>
  <span class="Delimiter">}</span>
  Current_routine<span class="Delimiter">-&gt;</span>state = WAITING<span class="Delimiter">;</span>
  Current_routine<span class="Delimiter">-&gt;</span>waiting_on_routine_to_block = ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">);</span>
  trace<span class="Delimiter">(</span><span class="Constant">9998</span><span class="Delimiter">,</span> <span class="Constant">&quot;run&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;waiting for routine &quot;</span> &lt;&lt; ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot; to block&quot;</span> &lt;&lt; end<span class="Delimiter">();</span>
  <span class="Identifier">break</span><span class="Delimiter">;</span>
<span class="Delimiter">}</span>

<span class="Delimiter">:(before &quot;End Scheduler State Transitions&quot;)</span>
<span class="Comment">// Wake up any routines waiting for other routines to stop running.</span>
<span class="Normal">for</span> <span class="Delimiter">(</span><span class="Normal">int</span> i = <span class="Constant">0</span><span class="Delimiter">;</span> i &lt; SIZE<span class="Delimiter">(</span>Routines<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span>
  <span class="Normal">if</span> <span class="Delimiter">(</span>Routines<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">)-&gt;</span>state != WAITING<span class="Delimiter">)</span> <span class="Identifier">continue</span><span class="Delimiter">;</span>
  routine* waiter = Routines<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">);</span>
  <span class="Normal">if</span> <span class="Delimiter">(</span>!waiter<span class="Delimiter">-&gt;</span>waiting_on_routine_to_block<span class="Delimiter">)</span> <span class="Identifier">continue</span><span class="Delimiter">;</span>
  <span class="Normal">int</span> id = waiter<span class="Delimiter">-&gt;</span>waiting_on_routine_to_block<span class="Delimiter">;</span>
  assert<span class="Delimiter">(</span>id != waiter<span class="Delimiter">-&gt;</span>id<span class="Delimiter">);</span>  <span class="Comment">// routine can't wait on itself</span>
  <span class="Normal">for</span> <span class="Delimiter">(</span><span class="Normal">int</span> j = <span class="Constant">0</span><span class="Delimiter">;</span> j &lt; SIZE<span class="Delimiter">(</span>Routines<span class="Delimiter">);</span> ++j<span class="Delimiter">)</span> <span class="Delimiter">{</span>
    <span class="Normal">const</span> routine* waitee = Routines<span class="Delimiter">.</span>at<span class="Delimiter">(</span>j<span class="Delimiter">);</span>
    <span class="Normal">if</span> <span class="Delimiter">(</span>waitee<span class="Delimiter">-&gt;</span>id != id<span class="Delimiter">)</span> <span class="Identifier">continue</span><span class="Delimiter">;</span>
    <span class="Normal">if</span> <span class="Delimiter">(</span>waitee<span class="Delimiter">-&gt;</span>state != RUNNING || waitee<span class="Delimiter">-&gt;</span>blocked<span class="Delimiter">)</span> <span class="Delimiter">{</span>
      trace<span class="Delimiter">(</span><span class="Constant">9999</span><span class="Delimiter">,</span> <span class="Constant">&quot;schedule&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;waking up routine &quot;</span> &lt;&lt; waiter<span class="Delimiter">-&gt;</span>id &lt;&lt; <span class="Constant">&quot; because routine &quot;</span> &lt;&lt; waitee<span class="Delimiter">-&gt;</span>id &lt;&lt; <span class="Constant">&quot; is blocked&quot;</span> &lt;&lt; end<span class="Delimiter">();</span>
      waiter<span class="Delimiter">-&gt;</span>state = RUNNING<span class="Delimiter">;</span>
      waiter<span class="Delimiter">-&gt;</span>waiting_on_routine_to_block = <span class="Constant">0</span><span class="Delimiter">;</span>
    <span class="Delimiter">}</span>
  <span class="Delimiter">}</span>
<span class="Delimiter">}</span>

<span class="Comment">//: yield voluntarily to let some other routine run</span>

<span class="Delimiter">:(before &quot;End Primitive Recipe Declarations&quot;)</span>
SWITCH<span class="Delimiter">,</span>
<span class="Delimiter">:(before &quot;End Primitive Recipe Numbers&quot;)</span>
put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> <span class="Constant">&quot;switch&quot;</span><span class="Delimiter">,</span> SWITCH<span class="Delimiter">);</span>
<span class="Delimiter">:(before &quot;End Primitive Recipe Checks&quot;)</span>
<span class="Normal">case</span> SWITCH: <span class="Delimiter">{</span>
  <span class="Identifier">break</span><span class="Delimiter">;</span>
<span class="Delimiter">}</span>
<span class="Comment">//: pick another RUNNING routine at random and wait for it to get a chance</span>
<span class="Comment">//: there might be a better implementation than this</span>
<span class="Delimiter">:(before &quot;End Primitive Recipe Implementations&quot;)</span>
<span class="Normal">case</span> SWITCH: <span class="Delimiter">{</span>
  <span class="Normal">int</span> id = some_other_running_routine<span class="Delimiter">();</span>
  <span class="Normal">if</span> <span class="Delimiter">(</span>id<span class="Delimiter">)</span> <span class="Delimiter">{</span>
    assert<span class="Delimiter">(</span>id != Current_routine<span class="Delimiter">-&gt;</span>id<span class="Delimiter">);</span>
    Current_routine<span class="Delimiter">-&gt;</span>state = WAITING<span class="Delimiter">;</span>
    Current_routine<span class="Delimiter">-&gt;</span>waiting_on_routine_to_block = id<span class="Delimiter">;</span>
  <span class="Delimiter">}</span>
  <span class="Identifier">break</span><span class="Delimiter">;</span>
<span class="Delimiter">}</span>
<span class="Delimiter">:(code)</span>
<span class="Normal">int</span> some_other_running_routine<span class="Delimiter">()</span> <span class="Delimiter">{</span>
  <span class="Normal">for</span> <span class="Delimiter">(</span><span class="Normal">int</span> i = <span class="Constant">0</span><span class="Delimiter">;</span> i &lt; SIZE<span class="Delimiter">(</span>Routines<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span>
    <span class="Normal">if</span> <span class="Delimiter">(</span>i == Current_routine_index<span class="Delimiter">)</span> <span class="Identifier">continue</span><span class="Delimiter">;</span>
    assert<span class="Delimiter">(</span>Routines<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">)</span> != Current_routine<span class="Delimiter">);</span>
    assert<span class="Delimiter">(</span>Routines<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">)-&gt;</span>id != Current_routine<span class="Delimiter">-&gt;</span>id<span class="Delimiter">);</span>
    <span class="Normal">if</span> <span class="Delimiter">(</span>Routines<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">)-&gt;</span>state == RUNNING<span class="Delimiter">)</span>
      <span class="Identifier">return</span> Routines<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">)-&gt;</span>id<span class="Delimiter">;</span>
  <span class="Delimiter">}</span>
  <span class="Identifier">return</span> <span class="Constant">0</span><span class="Delimiter">;</span>
<span class="Delimiter">}</span>

<span class="Comment">//: helper for restarting blocking routines in tests</span>

<span class="Delimiter">:(before &quot;End Primitive Recipe Declarations&quot;)</span>
RESTART<span class="Delimiter">,</span>
<span class="Delimiter">:(before &quot;End Primitive Recipe Numbers&quot;)</span>
put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> <span class="Constant">&quot;restart&quot;</span><span class="Delimiter">,</span> RESTART<span class="Delimiter">);</span>
<span class="Delimiter">:(before &quot;End Primitive Recipe Checks&quot;)</span>
<span class="Normal">case</span> RESTART: <span class="Delimiter">{</span>
  <span class="Normal">if</span> <span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">)</span> != <span class="Constant">1</span><span class="Delimiter">)</span> <span class="Delimiter">{</span>
    raise &lt;&lt; maybe<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">).</span>name<span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;'restart' requires exactly one ingredient, but got '&quot;</span> &lt;&lt; inst<span class="Delimiter">.</span>original_string &lt;&lt; <span class="Constant">&quot;'</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span>
    <span class="Identifier">break</span><span class="Delimiter">;</span>
  <span class="Delimiter">}</span>
  <span class="Normal">if</span> <span class="Delimiter">(</span>!is_mu_number<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">)))</span> <span class="Delimiter">{</span>
    raise &lt;&lt; maybe<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">).</span>name<span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;first ingredient of 'restart' should be a routine id generated by 'start-running', but got '&quot;</span> &lt;&lt; inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>original_string &lt;&lt; <span class="Constant">&quot;'</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span>
    <span class="Identifier">break</span><span class="Delimiter">;</span>
  <span class="Delimiter">}</span>
  <span class="Identifier">break</span><span class="Delimiter">;</span>
<span class="Delimiter">}</span>
<span class="Delimiter">:(before &quot;End Primitive Recipe Implementations&quot;)</span>
<span class="Normal">case</span> RESTART: <span class="Delimiter">{</span>
  <span class="Normal">int</span> id = ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">);</span>
  <span class="Normal">for</span> <span class="Delimiter">(</span><span class="Normal">int</span> i = <span class="Constant">0</span><span class="Delimiter">;</span> i &lt; SIZE<span class="Delimiter">(</span>Routines<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span>
    <span class="Normal">if</span> <span class="Delimiter">(</span>Routines<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">)-&gt;</span>id == id<span class="Delimiter">)</span> <span class="Delimiter">{</span>
      <span class="Normal">if</span> <span class="Delimiter">(</span>Routines<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">)-&gt;</span>state == WAITING<span class="Delimiter">)</span>
        Routines<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">)-&gt;</span>state = RUNNING<span class="Delimiter">;</span>
      Routines<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">)-&gt;</span>blocked = <span class="Constant">false</span><span class="Delimiter">;</span>
      <span class="Identifier">break</span><span class="Delimiter">;</span>
    <span class="Delimiter">}</span>
  <span class="Delimiter">}</span>
  <span class="Identifier">break</span><span class="Delimiter">;</span>
<span class="Delimiter">}</span>

<span class="Delimiter">:(scenario cannot_restart_completed_routine)</span>
<span class="Special">% Scheduling_interval = 1;</span>
<span class="muRecipe">def</span> main [
  local-scope
  <span class="Normal">r</span>:num/routine-id<span class="Special"> &lt;- </span>start-running f
  <span class="Normal">x</span>:num<span class="Special"> &lt;- </span>copy <span class="Constant">0</span>  <span class="Comment"># wait for f to be scheduled</span>
  <span class="Comment"># r is COMPLETED by this point</span>
  restart r  <span class="Comment"># should have no effect</span>
  <span class="Normal">x</span>:num<span class="Special"> &lt;- </span>copy <span class="Constant">0</span>  <span class="Comment"># give f time to be scheduled (though it shouldn't be)</span>
]
<span class="muRecipe">def</span> f [
  <span class="Constant">1</span>:num/<span class="Special">raw &lt;- </span>copy <span class="Constant">1</span>
]
<span class="Comment"># shouldn't crash</span>

<span class="Delimiter">:(scenario restart_blocked_routine)</span>
<span class="Special">% Scheduling_interval = 1;</span>
<span class="muRecipe">def</span> main [
  local-scope
  <span class="Normal">r</span>:num/routine-id<span class="Special"> &lt;- </span>start-running f
  wait-<span class="Normal">for</span>-routine-to-block r  <span class="Comment"># get past the block in f below</span>
  restart r
  wait-<span class="Normal">for</span>-routine-to-block r  <span class="Comment"># should run f to completion</span>
]
<span class="Comment"># function with one block</span>
<span class="muRecipe">def</span> f [
  current-routine-is-blocked
  <span class="Comment"># 8 instructions of padding, many more than 'main' above</span>
  <span class="Constant">1</span>:num<span class="Special"> &lt;- </span>add <span class="Constant">1</span>:num<span class="Delimiter">,</span> <span class="Constant">1</span>
  <span class="Constant">1</span>:num<span class="Special"> &lt;- </span>add <span class="Constant">1</span>:num<span class="Delimiter">,</span> <span class="Constant">1</span>
  <span class="Constant">1</span>:num<span class="Special"> &lt;- </span>add <span class="Constant">1</span>:num<span class="Delimiter">,</span> <span class="Constant">1</span>
  <span class="Constant">1</span>:num<span class="Special"> &lt;- </span>add <span class="Constant">1</span>:num<span class="Delimiter">,</span> <span class="Constant">1</span>
  <span class="Constant">1</span>:num<span class="Special"> &lt;- </span>add <span class="Constant">1</span>:num<span class="Delimiter">,</span> <span class="Constant">1</span>
  <span class="Constant">1</span>:num<span class="Special"> &lt;- </span>add <span class="Constant">1</span>:num<span class="Delimiter">,</span> <span class="Constant">1</span>
  <span class="Constant">1</span>:num<span class="Special"> &lt;- </span>add <span class="Constant">1</span>:num<span class="Delimiter">,</span> <span class="Constant">1</span>
  <span class="Constant">1</span>:num<span class="Special"> &lt;- </span>add <span class="Constant">1</span>:num<span class="Delimiter">,</span> <span class="Constant">1</span>
  <span class="Constant">1</span>:num<span class="Special"> &lt;- </span>add <span class="Constant">1</span>:num<span class="Delimiter">,</span> <span class="Constant">1</span>
]
<span class="Comment"># make sure all of f ran</span>
<span class="traceContains">+mem: storing 8 in location 1</span>
</pre>
</body>
</html>
<!-- vim: set foldmethod=manual : -->