| ... | ... | @@ -310,58 +310,65 @@ pub fn spawn(pool: *Pool, comptime func: anytype, args: anytype) void { |
| 310 | 310 | pool.cond.signal(); |
| 311 | 311 | } |
| 312 | 312 | |
| 313 | fn acquireThreadToken(job_server_options: Options.JobServer, fd_ptr: *std.posix.fd_t) void { |
| 314 | if (fd_ptr.* >= 0) return; |
| 315 | |
| 316 | switch (job_server_options) { |
| 317 | .abstain => {}, |
| 318 | .connect, .host => |addr| { |
| 319 | const sockfd = std.posix.socket( |
| 320 | std.posix.AF.UNIX, |
| 321 | std.posix.SOCK.STREAM | std.posix.SOCK.CLOEXEC, |
| 322 | 0, |
| 323 | ) catch |err| { |
| 324 | std.log.debug("failed to make socket: {s}", .{@errorName(err)}); |
| 325 | return; |
| 326 | }; |
| 327 | fd_ptr.* = sockfd; |
| 328 | |
| 329 | std.posix.connect(sockfd, &addr.any, addr.getOsSockLen()) catch |err| { |
| 330 | std.log.debug("failed to connect: {s}", .{@errorName(err)}); |
| 331 | return; |
| 332 | }; |
| 333 | |
| 334 | var trash_buf: [1]u8 = undefined; |
| 335 | _ = std.posix.read(sockfd, &trash_buf) catch |err| { |
| 336 | std.log.debug("failed to read: {s}", .{@errorName(err)}); |
| 337 | return; |
| 338 | }; |
| 339 | }, |
| 340 | } |
| 341 | } |
| 342 | |
| 343 | fn releaseThreadToken(fd_ptr: *std.posix.fd_t) void { |
| 344 | const fd = fd_ptr.*; |
| 345 | if (fd >= 0) { |
| 346 | std.posix.close(fd); |
| 347 | fd_ptr.* = -1; |
| 348 | } |
| 349 | } |
| 350 | |
| 313 | 351 | fn worker(pool: *Pool) void { |
| 314 | | var trash_buf: [1]u8 = undefined; |
| 315 | | var connection: ?std.posix.fd_t = null; |
| 316 | | defer if (connection) |fd| std.posix.close(fd); |
| 352 | var connection: std.posix.fd_t = -1; |
| 353 | defer releaseThreadToken(&connection); |
| 317 | 354 | |
| 318 | 355 | pool.mutex.lock(); |
| 319 | 356 | defer pool.mutex.unlock(); |
| 320 | 357 | |
| 321 | 358 | while (true) { |
| 322 | | while (pool.run_queue.popFirst()) |run_node| { |
| 323 | | // Temporarily unlock the mutex in order to execute the run_node. |
| 359 | const work_available = pool.run_queue.first != null; |
| 360 | if (work_available) { |
| 324 | 361 | pool.mutex.unlock(); |
| 325 | 362 | defer pool.mutex.lock(); |
| 326 | | |
| 327 | | if (connection == null) switch (pool.job_server_options) { |
| 328 | | .abstain => {}, |
| 329 | | .connect, .host => |addr| lock: { |
| 330 | | const sockfd = std.posix.socket( |
| 331 | | std.posix.AF.UNIX, |
| 332 | | std.posix.SOCK.STREAM | std.posix.SOCK.CLOEXEC, |
| 333 | | 0, |
| 334 | | ) catch |err| { |
| 335 | | std.log.debug("failed to make socket: {s}", .{@errorName(err)}); |
| 336 | | break :lock; |
| 337 | | }; |
| 338 | | connection = sockfd; |
| 339 | | |
| 340 | | std.posix.connect(sockfd, &addr.any, addr.getOsSockLen()) catch |err| { |
| 341 | | std.log.debug("failed to connect: {s}", .{@errorName(err)}); |
| 342 | | break :lock; |
| 343 | | }; |
| 344 | | |
| 345 | | _ = std.posix.read(sockfd, &trash_buf) catch |err| { |
| 346 | | std.log.debug("failed to read: {s}", .{@errorName(err)}); |
| 347 | | break :lock; |
| 348 | | }; |
| 349 | | }, |
| 350 | | }; |
| 351 | | |
| 352 | | const runFn = run_node.data.runFn; |
| 353 | | runFn(&run_node.data); |
| 363 | acquireThreadToken(pool.job_server_options, &connection); |
| 354 | 364 | } |
| 355 | | |
| 356 | | // Stop executing instead of waiting if the thread pool is no longer running. |
| 357 | | if (pool.end_flag) |
| 358 | | break; |
| 359 | | |
| 360 | | if (connection) |fd| { |
| 361 | | std.posix.close(fd); |
| 362 | | connection = null; |
| 365 | while (pool.run_queue.popFirst()) |run_node| { |
| 366 | pool.mutex.unlock(); |
| 367 | defer pool.mutex.lock(); |
| 368 | run_node.data.runFn(&run_node.data); |
| 363 | 369 | } |
| 364 | | |
| 370 | if (pool.end_flag) return; |
| 371 | releaseThreadToken(&connection); |
| 365 | 372 | pool.cond.wait(&pool.mutex); |
| 366 | 373 | } |
| 367 | 374 | } |