Skip to content

Commit c89aac8

Browse files
committed
better workaround for guaranteeing memory in coroutine frame
See #1194
1 parent 1a1534e commit c89aac8

File tree

2 files changed

+43
-22
lines changed

2 files changed

+43
-22
lines changed

std/atomic/queue_mpsc.zig

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,31 @@ pub fn QueueMpsc(comptime T: type) type {
6060
}
6161
return self.outbox.isEmpty();
6262
}
63+
64+
/// For debugging only. No API guarantees about what this does.
65+
pub fn dump(self: *Self) void {
66+
{
67+
var it = self.outbox.root;
68+
while (it) |node| {
69+
std.debug.warn("0x{x} -> ", @ptrToInt(node));
70+
it = node.next;
71+
}
72+
}
73+
const inbox_index = self.inbox_index;
74+
const inboxes = []*std.atomic.Stack(T){
75+
&self.inboxes[self.inbox_index],
76+
&self.inboxes[1 - self.inbox_index],
77+
};
78+
for (inboxes) |inbox| {
79+
var it = inbox.root;
80+
while (it) |node| {
81+
std.debug.warn("0x{x} -> ", @ptrToInt(node));
82+
it = node.next;
83+
}
84+
}
85+
86+
std.debug.warn("null\n");
87+
}
6388
};
6489
}
6590

std/event.zig

Lines changed: 18 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -439,15 +439,14 @@ pub const Loop = struct {
439439

440440
pub async fn waitFd(self: *Loop, fd: i32) !void {
441441
defer self.removeFd(fd);
442-
var resume_node = ResumeNode{
443-
.id = ResumeNode.Id.Basic,
444-
.handle = undefined,
445-
};
446442
suspend |p| {
447-
resume_node.handle = p;
443+
// TODO explicitly put this memory in the coroutine frame #1194
444+
var resume_node = ResumeNode{
445+
.id = ResumeNode.Id.Basic,
446+
.handle = p,
447+
};
448448
try self.addFd(fd, &resume_node);
449449
}
450-
var a = &resume_node; // TODO better way to explicitly put memory in coro frame
451450
}
452451

453452
/// Bring your own linked list node. This means it can't fail.
@@ -618,8 +617,7 @@ pub const Loop = struct {
618617
while (true) {
619618
var nbytes: windows.DWORD = undefined;
620619
var overlapped: ?*windows.OVERLAPPED = undefined;
621-
switch (std.os.windowsGetQueuedCompletionStatus(self.os_data.io_port, &nbytes, &completion_key,
622-
&overlapped, windows.INFINITE)) {
620+
switch (std.os.windowsGetQueuedCompletionStatus(self.os_data.io_port, &nbytes, &completion_key, &overlapped, windows.INFINITE)) {
623621
std.os.WindowsWaitResult.Aborted => return,
624622
std.os.WindowsWaitResult.Normal => {},
625623
}
@@ -1062,10 +1060,13 @@ pub const Lock = struct {
10621060
}
10631061

10641062
pub async fn acquire(self: *Lock) Held {
1065-
var my_tick_node: Loop.NextTickNode = undefined;
1066-
10671063
s: suspend |handle| {
1068-
my_tick_node.data = handle;
1064+
// TODO explicitly put this memory in the coroutine frame #1194
1065+
var my_tick_node = Loop.NextTickNode{
1066+
.data = handle,
1067+
.next = undefined,
1068+
};
1069+
10691070
self.queue.put(&my_tick_node);
10701071

10711072
// At this point, we are in the queue, so we might have already been resumed and this coroutine
@@ -1107,10 +1108,6 @@ pub const Lock = struct {
11071108
}
11081109
}
11091110

1110-
// TODO this workaround to force my_tick_node to be in the coroutine frame should
1111-
// not be necessary
1112-
var trash1 = &my_tick_node;
1113-
11141111
return Held{ .lock = self };
11151112
}
11161113
};
@@ -1176,6 +1173,10 @@ test "std.event.Lock" {
11761173
}
11771174

11781175
async fn testLock(loop: *Loop, lock: *Lock) void {
1176+
// TODO explicitly put next tick node memory in the coroutine frame #1194
1177+
suspend |p| {
1178+
resume p;
1179+
}
11791180
const handle1 = async lockRunner(lock) catch @panic("out of memory");
11801181
var tick_node1 = Loop.NextTickNode{
11811182
.next = undefined,
@@ -1200,12 +1201,6 @@ async fn testLock(loop: *Loop, lock: *Lock) void {
12001201
await handle1;
12011202
await handle2;
12021203
await handle3;
1203-
1204-
// TODO this is to force tick node memory to be in the coro frame
1205-
// there should be a way to make it explicit where the memory is
1206-
var a = &tick_node1;
1207-
var b = &tick_node2;
1208-
var c = &tick_node3;
12091204
}
12101205

12111206
var shared_test_data = [1]i32{0} ** 10;
@@ -1216,7 +1211,8 @@ async fn lockRunner(lock: *Lock) void {
12161211

12171212
var i: usize = 0;
12181213
while (i < shared_test_data.len) : (i += 1) {
1219-
const handle = await (async lock.acquire() catch @panic("out of memory"));
1214+
const lock_promise = async lock.acquire() catch @panic("out of memory");
1215+
const handle = await lock_promise;
12201216
defer handle.release();
12211217

12221218
shared_test_index = 0;

0 commit comments

Comments
 (0)