| ... | ... | @@ -12,15 +12,18 @@ const maxInt = std.math.maxInt; |
| 12 | 12 | const Thread = std.Thread; |
| 13 | 13 | |
| 14 | 14 | pub const Loop = struct { |
| 15 | | allocator: *mem.Allocator, |
| 16 | 15 | next_tick_queue: std.atomic.Queue(anyframe), |
| 17 | 16 | os_data: OsData, |
| 18 | 17 | final_resume_node: ResumeNode, |
| 19 | 18 | pending_event_count: usize, |
| 20 | 19 | extra_threads: []*Thread, |
| 21 | 20 | |
| 22 | | // pre-allocated eventfds. all permanently active. |
| 23 | | // this is how we send promises to be resumed on other threads. |
| 21 | /// For resources that have the same lifetime as the `Loop`. |
| 22 | /// This is only used by `Loop` for the thread pool and associated resources. |
| 23 | arena: std.heap.ArenaAllocator, |
| 24 | |
| 25 | /// Pre-allocated eventfds. All permanently active. |
| 26 | /// This is how `Loop` sends promises to be resumed on other threads. |
| 24 | 27 | available_eventfd_resume_nodes: std.atomic.Stack(ResumeNode.EventFd), |
| 25 | 28 | eventfd_resume_nodes: []std.atomic.Stack(ResumeNode.EventFd).Node, |
| 26 | 29 | |
| ... | ... | @@ -127,11 +130,9 @@ pub const Loop = struct { |
| 127 | 130 | /// Thread count is the total thread count. The thread pool size will be |
| 128 | 131 | /// max(thread_count - 1, 0) |
| 129 | 132 | pub fn initThreadPool(self: *Loop, thread_count: usize) !void { |
| 130 | | // TODO: https://github.com/ziglang/zig/issues/3539 |
| 131 | | const allocator = std.heap.page_allocator; |
| 132 | 133 | self.* = Loop{ |
| 134 | .arena = std.heap.ArenaAllocator.init(std.heap.page_allocator), |
| 133 | 135 | .pending_event_count = 1, |
| 134 | | .allocator = allocator, |
| 135 | 136 | .os_data = undefined, |
| 136 | 137 | .next_tick_queue = std.atomic.Queue(anyframe).init(), |
| 137 | 138 | .extra_threads = undefined, |
| ... | ... | @@ -143,17 +144,17 @@ pub const Loop = struct { |
| 143 | 144 | .overlapped = ResumeNode.overlapped_init, |
| 144 | 145 | }, |
| 145 | 146 | }; |
| 147 | errdefer self.arena.deinit(); |
| 148 | |
| 146 | 149 | // We need at least one of these in case the fs thread wants to use onNextTick |
| 147 | 150 | const extra_thread_count = thread_count - 1; |
| 148 | 151 | const resume_node_count = std.math.max(extra_thread_count, 1); |
| 149 | | self.eventfd_resume_nodes = try self.allocator.alloc( |
| 152 | self.eventfd_resume_nodes = try self.arena.allocator.alloc( |
| 150 | 153 | std.atomic.Stack(ResumeNode.EventFd).Node, |
| 151 | 154 | resume_node_count, |
| 152 | 155 | ); |
| 153 | | errdefer self.allocator.free(self.eventfd_resume_nodes); |
| 154 | 156 | |
| 155 | | self.extra_threads = try self.allocator.alloc(*Thread, extra_thread_count); |
| 156 | | errdefer self.allocator.free(self.extra_threads); |
| 157 | self.extra_threads = try self.arena.allocator.alloc(*Thread, extra_thread_count); |
| 157 | 158 | |
| 158 | 159 | try self.initOsData(extra_thread_count); |
| 159 | 160 | errdefer self.deinitOsData(); |
| ... | ... | @@ -161,7 +162,8 @@ pub const Loop = struct { |
| 161 | 162 | |
| 162 | 163 | pub fn deinit(self: *Loop) void { |
| 163 | 164 | self.deinitOsData(); |
| 164 | | self.allocator.free(self.extra_threads); |
| 165 | self.arena.deinit(); |
| 166 | self.* = undefined; |
| 165 | 167 | } |
| 166 | 168 | |
| 167 | 169 | const InitOsDataError = os.EpollCreateError || mem.Allocator.Error || os.EventFdError || |
| ... | ... | @@ -407,7 +409,6 @@ pub const Loop = struct { |
| 407 | 409 | noasync os.close(self.os_data.final_eventfd); |
| 408 | 410 | while (self.available_eventfd_resume_nodes.pop()) |node| noasync os.close(node.data.eventfd); |
| 409 | 411 | noasync os.close(self.os_data.epollfd); |
| 410 | | self.allocator.free(self.eventfd_resume_nodes); |
| 411 | 412 | }, |
| 412 | 413 | .macosx, .freebsd, .netbsd, .dragonfly => { |
| 413 | 414 | noasync os.close(self.os_data.kqfd); |