1+ import asyncio
12import logging
23from typing import Awaitable , Callable , Dict , Optional , Set , Tuple , Type , Union
34
@@ -48,10 +49,22 @@ def __init__(
4849 wiring = self .add_exposing_wiring (wiring , expose )
4950 super ().__init__ (wiring , state_consumer , state_producer )
5051
52+ reads_from_external : bool = False
53+ for component in self ._wiring :
54+ input_components = [
55+ p .component for p in self ._wiring [component ].values () # type: ignore
56+ ]
57+ if "external" in input_components :
58+ reads_from_external = True
59+ break
60+
61+ self .reads_from_external = reads_from_external
5162 self .raise_interrupt = raise_interrupt
5263 self .interrupts : Set [ComponentID ] = set ()
5364 self .component_error : ComponentException
5465
66+ self .first_tick : asyncio .Event = asyncio .Event ()
67+
5568 @staticmethod
5669 def add_exposing_wiring (
5770 wiring : Union [Wiring , InverseWiring ],
@@ -127,17 +140,20 @@ async def on_tick(
127140 wakeup_components = {
128141 component for component , when in self .wakeups .items () if when <= time
129142 }
130- root_components : Set [ComponentID ] = {
131- * self .interrupts ,
132- * wakeup_components ,
133- ComponentID ("external" ),
134- }
143+
144+ root_components : Set [ComponentID ] = {* self .interrupts , * wakeup_components }
145+
146+ if self .reads_from_external :
147+ root_components .update ([ComponentID ("external" )])
148+
135149 for component in wakeup_components :
136150 del self .wakeups [component ]
137151 self .interrupts .clear ()
138152
139153 self .input_changes = changes
140154 self .output_changes = Changes (Map ())
155+
156+ await asyncio .wait_for (self .first_tick .wait (), timeout = 30 )
141157 await self .ticker (time , root_components )
142158
143159 _ , call_at = self .get_first_wakeups ()
@@ -146,6 +162,11 @@ async def on_tick(
146162 async def run_forever (self ) -> None :
147163 """Delegates to setup which instantiates the ticker and state interfaces."""
148164 await self .setup ()
165+ await self .ticker (
166+ SimTime (0 ),
167+ self .ticker .components ,
168+ )
169+ self .first_tick .set ()
149170
150171 async def schedule_interrupt (self , source : ComponentID ) -> None :
151172 """Schedules the interrupt of a component immediately.
0 commit comments