@@ -354,22 +354,6 @@ def write(self, vs):
354354 assert (all (v == () for v in vs ))
355355 self .progress += len (vs )
356356
357- #### Context-Local Storage
358-
359- class ContextLocalStorage :
360- LENGTH = 1
361- array : list [int ]
362-
363- def __init__ (self ):
364- self .array = [0 ] * ContextLocalStorage .LENGTH
365-
366- def set (self , i , v ):
367- assert (types_match_values (['i32' ], [v ]))
368- self .array [i ] = v
369-
370- def get (self , i ):
371- return self .array [i ]
372-
373357#### Waitable State
374358
375359class EventCode (IntEnum ):
@@ -471,7 +455,6 @@ class State(Enum):
471455 supertask : Optional [Task ]
472456 on_resolve : Callable [[Optional [list [any ]]], None ]
473457 num_borrows : int
474- context : ContextLocalStorage
475458
476459 def __init__ (self , opts , inst , ft , supertask , on_resolve ):
477460 self .state = Task .State .INITIAL
@@ -481,7 +464,6 @@ def __init__(self, opts, inst, ft, supertask, on_resolve):
481464 self .supertask = supertask
482465 self .on_resolve = on_resolve
483466 self .num_borrows = 0
484- self .context = ContextLocalStorage ()
485467
486468 async def enter (self , thread ):
487469 self .trap_if_on_the_stack (self .inst )
@@ -874,13 +856,19 @@ def drop(self):
874856
875857class Thread :
876858 task : Task
877- future : Optional [asyncio .Future ]
859+ index : int
860+ context : list [int ]
861+ future : Optional [Awaitable ]
878862 on_resume : Optional [asyncio .Future ]
879863 on_suspend_or_exit : Optional [asyncio .Future ]
880864 returned : bool
881865
866+ CONTEXT_LENGTH = 1
867+
882868 def __init__ (self , task , coro ):
883869 self .task = task
870+ self .index = task .inst .table .add (self )
871+ self .context = [0 ] * Thread .CONTEXT_LENGTH
884872 self .future = None
885873 self .on_resume = asyncio .Future ()
886874 self .on_suspend_or_exit = None
@@ -890,6 +878,7 @@ async def async_impl():
890878 self .on_resume = None
891879 await coro
892880 self .on_suspend_or_exit .set_result (None )
881+ self .task .inst .table .remove (self .index )
893882 self .returned = True
894883 asyncio .create_task (async_impl ())
895884
@@ -917,6 +906,30 @@ async def suspend(self, future) -> Cancelled:
917906 self .on_resume = None
918907 return cancelled
919908
909+ async def switch (self , other : Thread ) -> Cancelled :
910+ assert (not self .future and not other .future )
911+ assert (self .on_suspend_or_exit and not other .on_suspend_or_exit )
912+ other .on_suspend_or_exit = self .on_suspend_or_exit
913+ self .on_suspend_or_exit = None
914+ other .on_resume .set_result (Cancelled .FALSE )
915+ assert (not self .on_resume )
916+ self .on_resume = asyncio .Future ()
917+ cancelled = await self .on_resume
918+ self .on_resume = None
919+ return cancelled
920+
921+ def yield_ (self , other : Thread ) -> Cancelled :
922+ # deterministically switch to other, but leave this thread unblocked
923+ TODO
924+
925+ def unblock (self , other : Thread ):
926+ # unblock other, but deterministically keep running here
927+ TODO
928+
929+ def wait (self ) -> Cancelled :
930+ # perform just the first half of switch
931+ TODO
932+
920933#### Store State / Embedding API
921934
922935class Store :
@@ -2096,19 +2109,76 @@ async def canon_resource_rep(rt, thread, i):
20962109 trap_if (h .rt is not rt )
20972110 return [h .rep ]
20982111
2112+ ### 🧵 `canon thread.index`
2113+
2114+ async def canon_thread_index (shared , thread ):
2115+ assert (not shared )
2116+ return [thread .index ]
2117+
2118+ ### 🧵 `canon thread.new_indirect`
2119+
2120+ async def canon_thread_new_indirect (shared , ft , ftbl , thread , i , c ):
2121+ assert (not shared )
2122+ inst = thread .task .inst
2123+ trap_if (not inst .may_leave )
2124+ f = ftbl .get (i )
2125+ trap_if (f is None )
2126+ trap_if (f .type != ft )
2127+ thread = Thread (thread .task , f (c ))
2128+ return [thread .index ]
2129+
2130+ ### 🧵 `canon thread.switch`
2131+
2132+ async def canon_thread_switch (shared , thread , i ):
2133+ assert (not shared )
2134+ trap_if (not thread .task .inst .may_leave )
2135+ other = thread .task .inst .table .get (i )
2136+ trap_if (not isinstance (other , Thread ))
2137+ cancelled = await thread .switch (other )
2138+ return [ 1 if cancelled else 0 ]
2139+
2140+ ### 🧵 `canon thread.yield`
2141+
2142+ async def canon_thread_yield (shared , thread , i ):
2143+ assert (not shared )
2144+ trap_if (not thread .task .inst .may_leave )
2145+ other = thread .task .inst .table .get (i )
2146+ trap_if (not isinstance (other , Thread ))
2147+ other .yield_ (other )
2148+ return []
2149+
2150+ ### 🧵 `canon thread.unblock`
2151+
2152+ async def canon_thread_unblock (shared , thread , i ):
2153+ trap_if (not thread .task .inst .may_leave )
2154+ other = thread .task .inst .table .get (i )
2155+ trap_if (not isinstance (other , Thread ))
2156+ thread .unblock ()
2157+ return []
2158+
2159+ ### 🧵 `canon thread.wait`
2160+
2161+ async def canon_thread_wait (shared , thread , i ):
2162+ assert (not shared )
2163+ trap_if (not thread .task .inst .may_leave )
2164+ other = thread .task .inst .table .get (i )
2165+ trap_if (not isinstance (other , Thread ))
2166+ cancelled = await thread .suspend ()
2167+ return [ 1 if cancelled else 0 ]
2168+
20992169### 🔀 `canon context.get`
21002170
21012171async def canon_context_get (t , i , thread ):
21022172 assert (t == 'i32' )
2103- assert (i < ContextLocalStorage . LENGTH )
2104- return [thread .task . context . get ( i ) ]
2173+ assert (i < Thread . CONTEXT_LENGTH )
2174+ return [thread .context [ i ] ]
21052175
21062176### 🔀 `canon context.set`
21072177
21082178async def canon_context_set (t , i , thread , v ):
21092179 assert (t == 'i32' )
2110- assert (i < ContextLocalStorage . LENGTH )
2111- thread .task . context . set ( i , v )
2180+ assert (i < Thread . CONTEXT_LENGTH )
2181+ thread .context [ i ] = v
21122182 return []
21132183
21142184### 🔀 `canon backpressure.set`
0 commit comments