@@ -111,6 +111,8 @@ func notetsleepg(n *note, ns int64) bool {
111
111
gopark (nil , nil , waitReasonSleep , traceEvNone , 1 )
112
112
113
113
clearTimeoutEvent (id ) // note might have woken early, clear timeout
114
+ clearIdleID ()
115
+
114
116
mp = acquirem ()
115
117
delete (notes , n )
116
118
delete (notesWithTimeout , n )
@@ -148,10 +150,25 @@ var isHandlingEvent = false
148
150
var nextEventIsAsync = false
149
151
var returnedEventHandler * g
150
152
153
+ // The timeout event started by beforeIdle.
154
+ var idleID int32
155
+
151
156
// beforeIdle gets called by the scheduler if no goroutine is awake.
152
157
// If we are not already handling an event, then we pause for an async event.
153
158
// If an event handler returned, we resume it and it will pause the execution.
154
- func beforeIdle () bool {
159
+ func beforeIdle (delay int64 ) bool {
160
+ if delay > 0 {
161
+ if delay < 1e6 {
162
+ delay = 1
163
+ } else if delay < 1e15 {
164
+ delay = delay / 1e6
165
+ } else {
166
+ // An arbitrary cap on how long to wait for a timer.
167
+ // 1e9 ms == ~11.5 days.
168
+ delay = 1e9
169
+ }
170
+ idleID = scheduleTimeoutEvent (delay )
171
+ }
155
172
if ! isHandlingEvent {
156
173
nextEventIsAsync = true
157
174
pause (getcallersp () - 16 )
@@ -164,6 +181,14 @@ func beforeIdle() bool {
164
181
return false
165
182
}
166
183
184
+ // clearIdleID clears our record of the timeout started by beforeIdle.
185
+ func clearIdleID () {
186
+ if idleID != 0 {
187
+ clearTimeoutEvent (idleID )
188
+ idleID = 0
189
+ }
190
+ }
191
+
167
192
// pause sets SP to newsp and pauses the execution of Go's WebAssembly code until an event is triggered.
168
193
func pause (newsp uintptr )
169
194
@@ -189,6 +214,8 @@ func handleEvent() {
189
214
190
215
eventHandler ()
191
216
217
+ clearIdleID ()
218
+
192
219
// wait until all goroutines are idle
193
220
returnedEventHandler = getg ()
194
221
gopark (nil , nil , waitReasonZero , traceEvNone , 1 )
0 commit comments