From ef7db9717ec6b08a7ef7ed043819bf4855e0a828 Mon Sep 17 00:00:00 2001 From: LemonBoy Date: Wed, 9 Dec 2020 20:42:08 +0100 Subject: std: introduce meta.traits.is{Integral,Float} --- lib/std/meta/trait.zig | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) (limited to 'lib') diff --git a/lib/std/meta/trait.zig b/lib/std/meta/trait.zig index a288b2adfd..eb294a857c 100644 --- a/lib/std/meta/trait.zig +++ b/lib/std/meta/trait.zig @@ -312,6 +312,38 @@ test "std.meta.trait.isNumber" { testing.expect(!isNumber(NotANumber)); } +pub fn isIntegral(comptime T: type) bool { + return switch (@typeInfo(T)) { + .Int, .ComptimeInt => true, + else => false, + }; +} + +test "isIntegral" { + testing.expect(isIntegral(u32)); + testing.expect(!isIntegral(f32)); + testing.expect(isIntegral(@TypeOf(102))); + testing.expect(!isIntegral(@TypeOf(102.123))); + testing.expect(!isIntegral(*u8)); + testing.expect(!isIntegral([]u8)); +} + +pub fn isFloat(comptime T: type) bool { + return switch (@typeInfo(T)) { + .Float, .ComptimeFloat => true, + else => false, + }; +} + +test "isFloat" { + testing.expect(!isFloat(u32)); + testing.expect(isFloat(f32)); + testing.expect(!isFloat(@TypeOf(102))); + testing.expect(isFloat(@TypeOf(102.123))); + testing.expect(!isFloat(*f64)); + testing.expect(!isFloat([]f32)); +} + pub fn isConstPtr(comptime T: type) bool { if (!comptime is(.Pointer)(T)) return false; return @typeInfo(T).Pointer.is_const; -- cgit v1.2.3 From 584451140843f8e1524f3cebf0ca3ab580685b3d Mon Sep 17 00:00:00 2001 From: LemonBoy Date: Wed, 9 Dec 2020 20:47:56 +0100 Subject: std: prevent instantiation of atomic.Int with non-integral types --- lib/std/atomic/int.zig | 3 +++ 1 file changed, 3 insertions(+) (limited to 'lib') diff --git a/lib/std/atomic/int.zig b/lib/std/atomic/int.zig index 155a340b0a..cdbf4ca81e 100644 --- a/lib/std/atomic/int.zig +++ b/lib/std/atomic/int.zig @@ -10,6 +10,9 @@ const testing = std.testing; /// Thread-safe, lock-free integer pub fn Int(comptime T: type) type { + if (!std.meta.trait.isIntegral(T)) + @compileError("Expected integral type, got '" ++ @typeName(T) ++ "'"); + return extern struct { unprotected_value: T, -- cgit v1.2.3 From 5e91cc2fe38cd5fd4a481629ba1d72a8c66b46e6 Mon Sep 17 00:00:00 2001 From: LemonBoy Date: Wed, 9 Dec 2020 21:04:39 +0100 Subject: std: Validate the atomic ordering parameter in atomic.Int --- lib/std/atomic/bool.zig | 12 ++++++++++++ lib/std/atomic/int.zig | 12 ++++++++++++ 2 files changed, 24 insertions(+) (limited to 'lib') diff --git a/lib/std/atomic/bool.zig b/lib/std/atomic/bool.zig index c686fdfae0..27a265bbc1 100644 --- a/lib/std/atomic/bool.zig +++ b/lib/std/atomic/bool.zig @@ -21,14 +21,26 @@ pub const Bool = extern struct { // xchg is only valid rmw operation for a bool /// Atomically modifies memory and then returns the previous value. pub fn xchg(self: *Self, operand: bool, comptime ordering: std.builtin.AtomicOrder) bool { + switch (ordering) { + .Monotonic, .Acquire, .Release, .AcqRel, .SeqCst => {}, + else => @compileError("Invalid ordering '" ++ @tagName(ordering) ++ "' for a RMW operation"), + } return @atomicRmw(bool, &self.unprotected_value, .Xchg, operand, ordering); } pub fn load(self: *Self, comptime ordering: std.builtin.AtomicOrder) bool { + switch (ordering) { + .Unordered, .Monotonic, .Acquire, .SeqCst => {}, + else => @compileError("Invalid ordering '" ++ @tagName(ordering) ++ "' for a load operation"), + } return @atomicLoad(bool, &self.unprotected_value, ordering); } pub fn store(self: *Self, value: bool, comptime ordering: std.builtin.AtomicOrder) void { + switch (ordering) { + .Unordered, .Monotonic, .Release, .SeqCst => {}, + else => @compileError("Invalid ordering '" ++ @tagName(ordering) ++ "' for a store operation"), + } @atomicStore(bool, &self.unprotected_value, value, ordering); } }; diff --git a/lib/std/atomic/int.zig b/lib/std/atomic/int.zig index cdbf4ca81e..b06575e05f 100644 --- a/lib/std/atomic/int.zig +++ b/lib/std/atomic/int.zig @@ -24,14 +24,26 @@ pub fn Int(comptime T: type) type { /// Read, Modify, Write pub fn rmw(self: *Self, comptime op: builtin.AtomicRmwOp, operand: T, comptime ordering: builtin.AtomicOrder) T { + switch (ordering) { + .Monotonic, .Acquire, .Release, .AcqRel, .SeqCst => {}, + else => @compileError("Invalid ordering '" ++ @tagName(ordering) ++ "' for a RMW operation"), + } return @atomicRmw(T, &self.unprotected_value, op, operand, ordering); } pub fn load(self: *Self, comptime ordering: builtin.AtomicOrder) T { + switch (ordering) { + .Unordered, .Monotonic, .Acquire, .SeqCst => {}, + else => @compileError("Invalid ordering '" ++ @tagName(ordering) ++ "' for a load operation"), + } return @atomicLoad(T, &self.unprotected_value, ordering); } pub fn store(self: *Self, value: T, comptime ordering: builtin.AtomicOrder) void { + switch (ordering) { + .Unordered, .Monotonic, .Release, .SeqCst => {}, + else => @compileError("Invalid ordering '" ++ @tagName(ordering) ++ "' for a store operation"), + } @atomicStore(T, &self.unprotected_value, value, ordering); } -- cgit v1.2.3 From 88e3a7d6dc7289103b8a644aaf6a63437ff6b6b5 Mon Sep 17 00:00:00 2001 From: LemonBoy Date: Wed, 9 Dec 2020 21:34:28 +0100 Subject: std: Fix misuse of atomic.Int --- lib/std/os.zig | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'lib') diff --git a/lib/std/os.zig b/lib/std/os.zig index 3f63869a1a..e3afe90e5d 100644 --- a/lib/std/os.zig +++ b/lib/std/os.zig @@ -5214,7 +5214,7 @@ pub const CopyFileRangeError = error{ var has_copy_file_range_syscall = init: { const kernel_has_syscall = std.Target.current.os.isAtLeast(.linux, .{ .major = 4, .minor = 5 }) orelse true; - break :init std.atomic.Int(bool).init(kernel_has_syscall); + break :init std.atomic.Bool.init(kernel_has_syscall); }; /// Transfer data between file descriptors at specified offsets. @@ -5246,7 +5246,7 @@ pub fn copy_file_range(fd_in: fd_t, off_in: u64, fd_out: fd_t, off_out: u64, len const use_c = std.c.versionCheck(.{ .major = 2, .minor = 27, .patch = 0 }).ok; if (std.Target.current.os.tag == .linux and - (use_c or has_copy_file_range_syscall.get())) + (use_c or has_copy_file_range_syscall.load(.Monotonic))) { const sys = if (use_c) std.c else linux; @@ -5271,7 +5271,7 @@ pub fn copy_file_range(fd_in: fd_t, off_in: u64, fd_out: fd_t, off_out: u64, len EXDEV => {}, // syscall added in Linux 4.5, use fallback ENOSYS => { - has_copy_file_range_syscall.set(false); + has_copy_file_range_syscall.store(true, .Monotonic); }, else => |err| return unexpectedErrno(err), } -- cgit v1.2.3