mirror of
https://github.com/ziglang/zig.git
synced 2026-02-07 06:57:13 +00:00
77 lines
2.4 KiB
Zig
77 lines
2.4 KiB
Zig
pub fn ParallelHasher(comptime Hasher: type) type {
|
|
const hash_size = Hasher.digest_length;
|
|
|
|
return struct {
|
|
allocator: Allocator,
|
|
thread_pool: *ThreadPool,
|
|
|
|
pub fn hash(self: Self, file: fs.File, out: [][hash_size]u8, opts: struct {
|
|
chunk_size: u64 = 0x4000,
|
|
max_file_size: ?u64 = null,
|
|
}) !void {
|
|
const tracy = trace(@src());
|
|
defer tracy.end();
|
|
|
|
var wg: WaitGroup = .{};
|
|
|
|
const file_size = blk: {
|
|
const file_size = opts.max_file_size orelse try file.getEndPos();
|
|
break :blk std.math.cast(usize, file_size) orelse return error.Overflow;
|
|
};
|
|
const chunk_size = std.math.cast(usize, opts.chunk_size) orelse return error.Overflow;
|
|
|
|
const buffer = try self.allocator.alloc(u8, chunk_size * out.len);
|
|
defer self.allocator.free(buffer);
|
|
|
|
const results = try self.allocator.alloc(fs.File.PReadError!usize, out.len);
|
|
defer self.allocator.free(results);
|
|
|
|
{
|
|
wg.reset();
|
|
defer wg.wait();
|
|
|
|
for (out, results, 0..) |*out_buf, *result, i| {
|
|
const fstart = i * chunk_size;
|
|
const fsize = if (fstart + chunk_size > file_size)
|
|
file_size - fstart
|
|
else
|
|
chunk_size;
|
|
self.thread_pool.spawnWg(&wg, worker, .{
|
|
file,
|
|
fstart,
|
|
buffer[fstart..][0..fsize],
|
|
&(out_buf.*),
|
|
&(result.*),
|
|
});
|
|
}
|
|
}
|
|
for (results) |result| _ = try result;
|
|
}
|
|
|
|
fn worker(
|
|
file: fs.File,
|
|
fstart: usize,
|
|
buffer: []u8,
|
|
out: *[hash_size]u8,
|
|
err: *fs.File.PReadError!usize,
|
|
) void {
|
|
const tracy = trace(@src());
|
|
defer tracy.end();
|
|
err.* = file.preadAll(buffer, fstart);
|
|
Hasher.hash(buffer, out, .{});
|
|
}
|
|
|
|
const Self = @This();
|
|
};
|
|
}
|
|
|
|
const assert = std.debug.assert;
|
|
const fs = std.fs;
|
|
const mem = std.mem;
|
|
const std = @import("std");
|
|
const trace = @import("../../tracy.zig").trace;
|
|
|
|
const Allocator = mem.Allocator;
|
|
const ThreadPool = std.Thread.Pool;
|
|
const WaitGroup = std.Thread.WaitGroup;
|