diff options
Diffstat (limited to 'src/http/network_thread.zig')
-rw-r--r-- | src/http/network_thread.zig | 82 |
1 files changed, 82 insertions, 0 deletions
diff --git a/src/http/network_thread.zig b/src/http/network_thread.zig new file mode 100644 index 000000000..d3826dcb3 --- /dev/null +++ b/src/http/network_thread.zig @@ -0,0 +1,82 @@ +const ThreadPool = @import("thread_pool"); +pub const Batch = ThreadPool.Batch; +pub const Task = ThreadPool.Task; +const std = @import("std"); +const AsyncIO = @import("io"); + +const NetworkThread = @This(); + +/// Single-thread in this pool +pool: ThreadPool, + +pub var global: NetworkThread = undefined; +pub var global_loaded: std.atomic.Atomic(u32) = std.atomic.Atomic(u32).init(0); + +const CachedAddressList = struct { + address_list: *std.net.AddressList, + expire_after: u64, + key: u64, + index: ?u32 = null, + pub fn hash(name: []const u8, port: u16) u64 { + var hasher = std.hash.Wyhash.init(0); + hasher.update(name); + hasher.update(":"); + hasher.update(std.mem.asBytes(&port)); + return hasher.final(); + } + + pub fn init(key: u64, address_list: *std.net.AddressList, now: u64) CachedAddressList { + return CachedAddressList{ + .address_list = address_list, + .expire_after = now + std.time.ms_per_hour, + .key = key, + }; + } + + pub fn invalidate(this: *CachedAddressList) void { + this.address_list.deinit(); + _ = address_list_cached.remove(this.key); + } +}; + +const IdentityContext = struct { + pub fn eql(this: @This(), a: u64, b: u64) bool { + return a == b; + } + + pub fn hash(this: @This(), a: u64) u64 { + return a; + } +}; + +const AddressListCache = std.HashMap(u64, CachedAddressList, IdentityContext, 80); +var address_list_cached: AddressListCache = undefined; +pub fn getAddressList(allocator: *std.mem.Allocator, name: []const u8, port: u16) !*CachedAddressList { + const hash = CachedAddressList.hash(name, port); + const now = @intCast(u64, @maximum(0, std.time.milliTimestamp())); + if (address_list_cached.getPtr(hash)) |cached| { + if (cached.expire_after > now) { + return cached; + } + + cached.address_list.deinit(); + } + + const address_list = try std.net.getAddressList(allocator, name, port); + var entry = try address_list_cached.getOrPut(hash); + entry.value_ptr.* = CachedAddressList.init(hash, address_list, now); + return entry.value_ptr; +} + +pub fn init() !void { + if ((global_loaded.swap(1, .Monotonic)) == 1) return; + AsyncIO.global_loaded = true; + AsyncIO.global = try AsyncIO.init(1024, 0); + + global = NetworkThread{ + .pool = ThreadPool.init(.{ .max_threads = 1, .stack_size = 64 * 1024 * 1024 }), + }; + + global.pool.io = &AsyncIO.global; + address_list_cached = AddressListCache.init(@import("../global.zig").default_allocator); +} |