@@ -88,6 +88,7 @@ class InstanceType(ExternType):
8888class FuncType (ExternType ):
8989 params : list [tuple [str ,ValType ]]
9090 result : list [ValType | tuple [str ,ValType ]]
91+ async_ : bool = False
9192 def param_types (self ):
9293 return self .extract_types (self .params )
9394 def result_type (self ):
@@ -402,6 +403,7 @@ def resume(self, suspend_result = SuspendResult.NOT_CANCELLED):
402403 assert (not self .running ())
403404
404405 def suspend (self , cancellable ) -> SuspendResult :
406+ assert (self .task .may_block ())
405407 assert (self .running () and not self .cancellable and self .suspend_result is None )
406408 self .cancellable = cancellable
407409 self .parent_lock .release ()
@@ -420,6 +422,7 @@ def resume_later(self):
420422 self .task .inst .store .pending .append (self )
421423
422424 def suspend_until (self , ready_func , cancellable = False ) -> SuspendResult :
425+ assert (self .task .may_block ())
423426 assert (self .running ())
424427 if ready_func () and not DETERMINISTIC_PROFILE and random .randint (0 ,1 ):
425428 return SuspendResult .NOT_CANCELLED
@@ -566,8 +569,13 @@ def trap_if_on_the_stack(self, inst):
566569 def needs_exclusive (self ):
567570 return not self .opts .async_ or self .opts .callback
568571
572+ def may_block (self ):
573+ return self .ft .async_ or self .state == Task .State .RESOLVED
574+
569575 def enter (self , thread ):
570576 assert (thread in self .threads and thread .task is self )
577+ if not self .ft .async_ :
578+ return True
571579 def has_backpressure ():
572580 return self .inst .backpressure > 0 or (self .needs_exclusive () and self .inst .exclusive )
573581 if has_backpressure () or self .inst .num_waiting_to_enter > 0 :
@@ -584,6 +592,8 @@ def has_backpressure():
584592
585593 def exit (self ):
586594 assert (len (self .threads ) > 0 )
595+ if not self .ft .async_ :
596+ return
587597 if self .needs_exclusive ():
588598 assert (self .inst .exclusive )
589599 self .inst .exclusive = False
@@ -641,20 +651,6 @@ def ready_and_has_event():
641651 wset .num_waiting -= 1
642652 return event
643653
644- def poll_until (self , ready_func , thread , wset , cancellable ) -> Optional [EventTuple ]:
645- assert (thread in self .threads and thread .task is self )
646- wset .num_waiting += 1
647- match self .suspend_until (ready_func , thread , cancellable ):
648- case SuspendResult .CANCELLED :
649- event = (EventCode .TASK_CANCELLED , 0 , 0 )
650- case SuspendResult .NOT_CANCELLED :
651- if wset .has_pending_event ():
652- event = wset .get_pending_event ()
653- else :
654- event = (EventCode .NONE , 0 , 0 )
655- wset .num_waiting -= 1
656- return event
657-
658654 def yield_until (self , ready_func , thread , cancellable ) -> EventTuple :
659655 assert (thread in self .threads and thread .task is self )
660656 match self .suspend_until (ready_func , thread , cancellable ):
@@ -2028,15 +2024,17 @@ def thread_func(thread):
20282024 inst .exclusive = False
20292025 match code :
20302026 case CallbackCode .YIELD :
2031- event = task .yield_until (lambda : not inst .exclusive , thread , cancellable = True )
2027+ if task .may_block ():
2028+ event = task .yield_until (lambda : not inst .exclusive , thread , cancellable = True )
2029+ else :
2030+ event = (EventCode .NONE , 0 , 0 )
20322031 case CallbackCode .WAIT :
2032+ trap_if (not task .may_block ())
20332033 wset = inst .table .get (si )
20342034 trap_if (not isinstance (wset , WaitableSet ))
20352035 event = task .wait_until (lambda : not inst .exclusive , thread , wset , cancellable = True )
2036- case CallbackCode .POLL :
2037- wset = inst .table .get (si )
2038- trap_if (not isinstance (wset , WaitableSet ))
2039- event = task .poll_until (lambda : not inst .exclusive , thread , wset , cancellable = True )
2036+ case _:
2037+ trap ()
20402038 thread .in_event_loop = False
20412039 inst .exclusive = True
20422040 event_code , p1 , p2 = event
@@ -2053,8 +2051,7 @@ class CallbackCode(IntEnum):
20532051 EXIT = 0
20542052 YIELD = 1
20552053 WAIT = 2
2056- POLL = 3
2057- MAX = 3
2054+ MAX = 2
20582055
20592056def unpack_callback_result (packed ):
20602057 code = packed & 0xf
@@ -2074,6 +2071,8 @@ def call_and_trap_on_throw(callee, thread, args):
20742071
20752072def canon_lower (opts , ft , callee : FuncInst , thread , flat_args ):
20762073 trap_if (not thread .task .inst .may_leave )
2074+ trap_if (not thread .task .may_block () and ft .async_ and not opts .async_ )
2075+
20772076 subtask = Subtask ()
20782077 cx = LiftLowerContext (opts , thread .task .inst , subtask )
20792078
@@ -2113,6 +2112,7 @@ def on_resolve(result):
21132112 flat_results = lower_flat_values (cx , max_flat_results , result , ft .result_type (), flat_args )
21142113
21152114 subtask .callee = callee (thread .task , on_start , on_resolve )
2115+ assert (ft .async_ or subtask .state == Subtask .State .RETURNED )
21162116
21172117 if not opts .async_ :
21182118 if not subtask .resolved ():
@@ -2147,31 +2147,30 @@ def canon_resource_new(rt, thread, rep):
21472147
21482148### `canon resource.drop`
21492149
2150- def canon_resource_drop (rt , async_ , thread , i ):
2150+ def canon_resource_drop (rt , thread , i ):
21512151 trap_if (not thread .task .inst .may_leave )
21522152 inst = thread .task .inst
21532153 h = inst .table .remove (i )
21542154 trap_if (not isinstance (h , ResourceHandle ))
21552155 trap_if (h .rt is not rt )
21562156 trap_if (h .num_lends != 0 )
2157- flat_results = [] if not async_ else [0 ]
21582157 if h .own :
21592158 assert (h .borrow_scope is None )
21602159 if inst is rt .impl :
21612160 if rt .dtor :
21622161 rt .dtor (h .rep )
21632162 else :
21642163 if rt .dtor :
2165- caller_opts = CanonicalOptions (async_ = async_ )
2164+ caller_opts = CanonicalOptions (async_ = False )
21662165 callee_opts = CanonicalOptions (async_ = rt .dtor_async , callback = rt .dtor_callback )
2167- ft = FuncType ([U32Type ()],[])
2166+ ft = FuncType ([U32Type ()],[], async_ = False )
21682167 callee = partial (canon_lift , callee_opts , rt .impl , ft , rt .dtor )
2169- flat_results = canon_lower (caller_opts , ft , callee , thread , [h .rep ])
2168+ [] = canon_lower (caller_opts , ft , callee , thread , [h .rep ])
21702169 else :
21712170 thread .task .trap_if_on_the_stack (rt .impl )
21722171 else :
21732172 h .borrow_scope .num_borrows -= 1
2174- return flat_results
2173+ return []
21752174
21762175### `canon resource.rep`
21772176
@@ -2249,6 +2248,7 @@ def canon_waitable_set_new(thread):
22492248
22502249def canon_waitable_set_wait (cancellable , mem , thread , si , ptr ):
22512250 trap_if (not thread .task .inst .may_leave )
2251+ trap_if (not thread .task .may_block ())
22522252 wset = thread .task .inst .table .get (si )
22532253 trap_if (not isinstance (wset , WaitableSet ))
22542254 event = thread .task .wait_until (lambda : True , thread , wset , cancellable )
@@ -2267,7 +2267,12 @@ def canon_waitable_set_poll(cancellable, mem, thread, si, ptr):
22672267 trap_if (not thread .task .inst .may_leave )
22682268 wset = thread .task .inst .table .get (si )
22692269 trap_if (not isinstance (wset , WaitableSet ))
2270- event = thread .task .poll_until (lambda : True , thread , wset , cancellable )
2270+ if thread .task .deliver_pending_cancel (cancellable ):
2271+ event = (EventCode .TASK_CANCELLED , 0 , 0 )
2272+ elif not wset .has_pending_event ():
2273+ event = (EventCode .NONE , 0 , 0 )
2274+ else :
2275+ event = wset .get_pending_event ()
22712276 return unpack_event (mem , thread , ptr , event )
22722277
22732278### 🔀 `canon waitable-set.drop`
@@ -2299,6 +2304,7 @@ def canon_waitable_join(thread, wi, si):
22992304
23002305def canon_subtask_cancel (async_ , thread , i ):
23012306 trap_if (not thread .task .inst .may_leave )
2307+ trap_if (not thread .task .may_block () and not async_ )
23022308 subtask = thread .task .inst .table .get (i )
23032309 trap_if (not isinstance (subtask , Subtask ))
23042310 trap_if (subtask .resolve_delivered ())
@@ -2355,6 +2361,8 @@ def canon_stream_write(stream_t, opts, thread, i, ptr, n):
23552361
23562362def stream_copy (EndT , BufferT , event_code , stream_t , opts , thread , i , ptr , n ):
23572363 trap_if (not thread .task .inst .may_leave )
2364+ trap_if (not thread .task .may_block () and not opts .async_ )
2365+
23582366 e = thread .task .inst .table .get (i )
23592367 trap_if (not isinstance (e , EndT ))
23602368 trap_if (e .shared .t != stream_t .t )
@@ -2406,6 +2414,8 @@ def canon_future_write(future_t, opts, thread, i, ptr):
24062414
24072415def future_copy (EndT , BufferT , event_code , future_t , opts , thread , i , ptr ):
24082416 trap_if (not thread .task .inst .may_leave )
2417+ trap_if (not thread .task .may_block () and not opts .async_ )
2418+
24092419 e = thread .task .inst .table .get (i )
24102420 trap_if (not isinstance (e , EndT ))
24112421 trap_if (e .shared .t != future_t .t )
@@ -2456,6 +2466,7 @@ def canon_future_cancel_write(future_t, async_, thread, i):
24562466
24572467def cancel_copy (EndT , event_code , stream_or_future_t , async_ , thread , i ):
24582468 trap_if (not thread .task .inst .may_leave )
2469+ trap_if (not thread .task .may_block () and not async_ )
24592470 e = thread .task .inst .table .get (i )
24602471 trap_if (not isinstance (e , EndT ))
24612472 trap_if (e .shared .t != stream_or_future_t .t )
@@ -2532,6 +2543,7 @@ def canon_thread_switch_to(cancellable, thread, i):
25322543
25332544def canon_thread_suspend (cancellable , thread ):
25342545 trap_if (not thread .task .inst .may_leave )
2546+ trap_if (not thread .task .may_block ())
25352547 suspend_result = thread .task .suspend (thread , cancellable )
25362548 return [suspend_result ]
25372549
@@ -2559,6 +2571,8 @@ def canon_thread_yield_to(cancellable, thread, i):
25592571
25602572def canon_thread_yield (cancellable , thread ):
25612573 trap_if (not thread .task .inst .may_leave )
2574+ if not thread .task .may_block ():
2575+ return [SuspendResult .NOT_CANCELLED ]
25622576 event_code ,_ ,_ = thread .task .yield_until (lambda : True , thread , cancellable )
25632577 match event_code :
25642578 case EventCode .NONE :
0 commit comments