mirror of
https://github.com/ziglang/zig.git
synced 2026-01-06 21:43:25 +00:00
Merge pull request #7372 from LemonBoy/atomicint
Improvements for std.atomic.{Int,Bool}
This commit is contained in:
commit
a3de27ef3b
@ -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);
|
||||
}
|
||||
};
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -21,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);
|
||||
}
|
||||
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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),
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user