Last active
August 1, 2022 15:29
-
-
Save BruceChen7/a61ca9dab2385de822c8bac26baaaa3d to your computer and use it in GitHub Desktop.
#ziglang#type#zig#async
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 固定数组,类型体操 | |
// [Zig lang 初体验 -- 『大道至简』的 comptime - 纯纯的 Blog](https://blog.zhuangty.com/zig-lang-comptime/) | |
const std = @import("std"); | |
const ArrayList = std.ArrayList; | |
const DynamicBitSet = std.bit_set.DynamicBitSet; | |
fn FixedArray(comptime T: type) type { | |
return struct { | |
const Self = @This(); | |
data: ArrayList(T), | |
validity: DynamicBitSet, | |
pub const Ref = T; | |
pub fn deinit(self: *Self) void { | |
self.data.deinit(); | |
self.validity.deinit(); | |
} | |
pub fn value(self: *const Self, idx: usize) ?Self.Ref { | |
if (self.validity.isSet(idx)) { | |
return self.data.items[idx]; | |
} else { | |
return null; | |
} | |
} | |
pub fn len(self: *const Self) usize { | |
return self.data.len(); | |
} | |
}; | |
} | |
// 类型可以做逻辑 | |
// ... | |
const sizeLarge = (@sizeOf(T) > 8); | |
pub const Ref = if (sizeLarge > 8) *T else T; | |
// ... | |
pub fn value(self: *const Self, idx: usize) ?Self.Ref { | |
if (self.validity.isSet(idx)) { | |
if (sizeLarge) { | |
return &self.data.items[idx]; | |
} else { | |
return self.data.items[idx]; | |
} | |
} else { | |
return null; | |
} | |
} | |
const BytesArrayBuilder = struct { | |
const Self = @This(); | |
pub const Array = BytesArray; | |
data: ArrayList(u8), | |
offsets: ArrayList(u32), | |
validity: DynamicBitSet, | |
pub fn init(allocator: Allocator) !Self { | |
var offsets = try ArrayList(u32).initCapacity(allocator, 1); | |
offsets.appendAssumeCapacity(0); | |
return Self{ | |
.data = ArrayList(u8).init(allocator), | |
.offsets = offsets, | |
.validity = try DynamicBitSet.initEmpty(allocator, 0), | |
}; | |
} | |
fn append(self: *Self, v: Self.Array.Ref) !void { | |
try self.data.appendSlice(v); | |
try self.offsets.append(@intCast(u32, self.data.items.len)); | |
try self.validity.resize(self.validity.capacity() + 1, true); | |
} | |
fn append_null(self: *Self) !void { | |
try self.offsets.append(@intCast(u32, self.data.items.len)); | |
try self.validity.resize(self.validity.capacity() + 1, false); | |
} | |
pub fn finish(self: Self) BytesArray { | |
return BytesArray{ | |
.data = self.data, | |
.offsets = self.offsets, | |
.validity = self.validity, | |
}; | |
} | |
}; | |
// 定义 DataType,假设我们支持五种类型。 | |
const DataType = union(enum) { | |
SmallInt: void, | |
Integer: void, | |
BigInt: void, | |
Varchar: void, | |
Char: u16, // Char 的长度 | |
// 关联逻辑类型和物理类型 | |
fn ArrayType(self: DataType) type { | |
return switch (self) { | |
DataType.SmallInt => FixedArray(i16), | |
DataType.Integer => FixedArray(i32), | |
DataType.BigInt => FixedArray(i64), | |
DataType.Varchar => BytesArray, | |
DataType.Char => BytesArray, | |
}; | |
} | |
}; |
async in zig
// 阻塞模式
const net = @import("std").net;
pub fn main() !void {
const addr = try net.Address.parseIp("127.0.0.1", 7000);
try send_message(addr);
}
fn send_message(addr: net.Address) !void {
var socket = try net.tcpConnectToAddress(addr);
defer socket.close();
_ = try socket.write("Hello World!\n");
}
const net = @import("std").net;
// 采用事件模型
pub const io_mode = .evented;
pub fn main() !void {
const addr = try net.Address.parseIp("127.0.0.1", 7000);
try send_message(addr);
}
// 非阻塞模式,没有着色问题
fn send_message(addr: net.Address) !void {
var socket = try net.tcpConnectToAddress(addr);
defer socket.close();
_ = try socket.write("Hello World!\n");
}
着色问题
- 由于你不能从非async代码中调用async函数,你最终会有很多重复的工作,你需要重新实现部分标准库和所有网络相关的库,以考虑到async/await。这方面的一个例子是Python,在Python 3中引入async/await后,诞生了aio-libs这样的项目,其目标是在AsyncIO之上重新实现流行的网络库。
pub const BoolParser = struct {
// 是否支持
pub fn isSupported(comptime T: type) bool {
return switch (@typeInfo(T)) {
.Bool, .Int, .Float => true,
else => false,
};
}
pub fn parse(comptime T: type, comptime _: type, msg: anytype) !T {
const ch = try msg.readByte();
try msg.skipBytes(2, .{});
return switch (@typeInfo(T)) {
else => unreachable,
.Bool => ch == 't',
.Int, .Float => if (ch == 't') @as(T, 1) else @as(T, 0),
};
}
pub fn isSupportedAlloc(comptime T: type) bool {
return isSupported(T);
}
pub fn parseAlloc(comptime T: type, comptime rootParser: type, allocator: std.mem.Allocator, msg: anytype) !T {
_ = allocator;
return parse(T, rootParser, msg);
}
};
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
使用体验都跟 ArrayList 几乎完全一模一样,但是内部确实按字段列存储的,它的内部实现大量使用了编译期反射生成友好的代码。这对 Data-oriented Programming 的场景是非常友好的。