authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-07-09 21:21:59-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-07-09 21:21:59-04:00
logc89aac85c440ea4cbccf1abdbd6acf84a33077e3
treef1f759bbf0d6c071fcc5951d1515e9379c4853d8
parent1a1534ecb55d0273bd9cd62d415ac840eb73b2e5

better workaround for guaranteeing memory in coroutine frame

See #1194

2 files changed, 43 insertions(+), 22 deletions(-)

std/atomic/queue_mpsc.zig+25
......@@ -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+18-22
......@@ -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
11781175async 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
12111206var 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;