Skip to content

Commit 3466325

Browse files
authored
Merge pull request #610 from lightpanda-io/loop_interval_cleanup
Optimize intervals, and make sure they're probably cleaned up.
2 parents 1613345 + 6d8d688 commit 3466325

File tree

2 files changed

+23
-8
lines changed

2 files changed

+23
-8
lines changed

src/browser/browser.zig

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -267,7 +267,7 @@ pub const Page = struct {
267267
// load polyfills
268268
try polyfill.load(self.arena, self.scope);
269269

270-
// _ = try session.browser.app.loop.timeout(1 * std.time.ns_per_ms, &self.microtask_node);
270+
_ = try session.browser.app.loop.timeout(1 * std.time.ns_per_ms, &self.microtask_node);
271271
}
272272

273273
fn microtaskCallback(node: *Loop.CallbackNode, repeat_delay: *?u63) void {

src/runtime/loop.zig

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,9 @@ pub const Loop = struct {
4141
// event are finished.
4242
events_nb: usize,
4343

44+
// Used to stop repeating timeouts when loop.run is called.
45+
stopping: bool,
46+
4447
// ctx_id is incremented each time the loop is reset.
4548
// All callbacks store an initial ctx_id and compare before execution.
4649
// If a ctx is outdated, the callback is ignored.
@@ -62,11 +65,12 @@ pub const Loop = struct {
6265
pub const ConnectError = IO.ConnectError;
6366

6467
pub fn init(alloc: std.mem.Allocator) !Self {
65-
return Self{
68+
return .{
6669
.alloc = alloc,
6770
.cancelled = .{},
6871
.io = try IO.init(32, 0),
6972
.events_nb = 0,
73+
.stopping = false,
7074
.timeout_pool = MemoryPool(ContextTimeout).init(alloc),
7175
.event_callback_pool = MemoryPool(EventCallbackContext).init(alloc),
7276
};
@@ -98,6 +102,10 @@ pub const Loop = struct {
98102
// Note that I/O events callbacks might register more I/O events
99103
// on the go when they are executed (ie. nested I/O events).
100104
pub fn run(self: *Self) !void {
105+
// stop repeating / interval timeouts from re-registering
106+
self.stopping = true;
107+
defer self.stopping = false;
108+
101109
while (self.eventsNb() > 0) {
102110
try self.io.run_for_ns(10 * std.time.ns_per_ms);
103111
// at each iteration we might have new events registred by previous callbacks
@@ -134,6 +142,7 @@ pub const Loop = struct {
134142
const ContextTimeout = struct {
135143
loop: *Self,
136144
ctx_id: u32,
145+
initial: bool = true,
137146
callback_node: ?*CallbackNode,
138147
};
139148

@@ -145,8 +154,11 @@ pub const Loop = struct {
145154
var repeating = false;
146155
const loop = ctx.loop;
147156

148-
defer {
157+
if (ctx.initial) {
149158
loop.removeEvent();
159+
}
160+
161+
defer {
150162
if (repeating == false) {
151163
loop.timeout_pool.destroy(ctx);
152164
loop.alloc.destroy(completion);
@@ -174,10 +186,13 @@ pub const Loop = struct {
174186
if (ctx.callback_node) |cn| {
175187
var repeat_in: ?u63 = null;
176188
cn.func(cn, &repeat_in);
177-
if (repeat_in) |r| {
178-
// prevents our context and completion from being cleaned up
179-
repeating = true;
180-
loop.scheduleTimeout(r, ctx, completion);
189+
if (loop.stopping == false) {
190+
if (repeat_in) |r| {
191+
// prevents our context and completion from being cleaned up
192+
repeating = true;
193+
ctx.initial = false;
194+
loop.scheduleTimeout(r, ctx, completion);
195+
}
181196
}
182197
}
183198
}
@@ -195,12 +210,12 @@ pub const Loop = struct {
195210
.callback_node = callback_node,
196211
};
197212

213+
self.addEvent();
198214
self.scheduleTimeout(nanoseconds, ctx, completion);
199215
return @intFromPtr(completion);
200216
}
201217

202218
fn scheduleTimeout(self: *Self, nanoseconds: u63, ctx: *ContextTimeout, completion: *Completion) void {
203-
self.addEvent();
204219
self.io.timeout(*ContextTimeout, ctx, timeoutCallback, completion, nanoseconds);
205220
}
206221

0 commit comments

Comments
 (0)