pub fn assert(ok: bool) voidInvokes detectable illegal behavior when ok is false.
In debug and safe modes, calls to this function are always generated, and the unreachable statement triggers a panic.
In fast and small modes, calls to this function are optimized away, and in fact the optimizer is able to use the assertion in its heuristics.
Inside a test block, it is best to use the testing module rather than this function, because this function may not detect a test failure in fast and small mode. Outside of a test block, this assert function is the correct function to use.
pub fn deinit(af: *Atomic, io: Io) voidTo release all resources, always call deinit, even after a successful finish.
pub fn link(af: *Atomic, io: Io) LinkError!voidAtomically materializes the file into place, failing with error.PathAlreadyExists if something already exists there.
If this operation could not be done with an unnamed temporary file, the named temporary file will be deleted in a following operation, which may independently fail. The result of that operation is stored in delete_err.
pub fn replace(af: *Atomic, io: Io) ReplaceError!voidAtomically materializes the file into place, replacing any file that already exists there.
Calling this function requires setting CreateFileAtomicOptions.replace to true.
On Windows, this function introduces a period of time where some file system operations on the destination file will result in error.AccessDenied, including rename operations (such as the one used in this function).
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87const Atomic = @This();
const std = @import("../../std.zig");
const Io = std.Io;
const File = std.Io.File;
const Dir = std.Io.Dir;
const assert = std.debug.assert;
file: File,
file_basename_hex: u64,
file_open: bool,
file_exists: bool,
dir: Dir,
close_dir_on_deinit: bool,
dest_sub_path: []const u8,
pub const InitError = File.OpenError;
/// To release all resources, always call `deinit`, even after a successful
/// `finish`.
pub fn deinit(af: *Atomic, io: Io) void {
if (af.file_open) {
af.file.close(io);
af.file_open = false;
}
if (af.file_exists) {
const tmp_sub_path = std.fmt.hex(af.file_basename_hex);
af.dir.deleteFile(io, &tmp_sub_path) catch {};
af.file_exists = false;
}
if (af.close_dir_on_deinit) {
af.dir.close(io);
af.close_dir_on_deinit = false;
}
af.* = undefined;
}
pub const LinkError = File.HardLinkError || Dir.RenamePreserveError;
/// Atomically materializes the file into place, failing with
/// `error.PathAlreadyExists` if something already exists there.
///
/// If this operation could not be done with an unnamed temporary file, the
/// named temporary file will be deleted in a following operation, which may
/// independently fail. The result of that operation is stored in `delete_err`.
pub fn link(af: *Atomic, io: Io) LinkError!void {
if (af.file_exists) {
if (af.file_open) {
af.file.close(io);
af.file_open = false;
}
const tmp_sub_path = std.fmt.hex(af.file_basename_hex);
try af.dir.renamePreserve(&tmp_sub_path, af.dir, af.dest_sub_path, io);
af.file_exists = false;
} else {
assert(af.file_open);
try af.file.hardLink(io, af.dir, af.dest_sub_path, .{});
af.file.close(io);
af.file_open = false;
}
}
pub const ReplaceError = Dir.RenameError;
/// Atomically materializes the file into place, replacing any file that
/// already exists there.
///
/// Calling this function requires setting `CreateFileAtomicOptions.replace` to
/// `true`.
///
/// On Windows, this function introduces a period of time where some file
/// system operations on the destination file will result in
/// `error.AccessDenied`, including rename operations (such as the one used in
/// this function).
pub fn replace(af: *Atomic, io: Io) ReplaceError!void {
assert(af.file_exists); // Wrong value for `CreateFileAtomicOptions.replace`.
if (af.file_open) {
af.file.close(io);
af.file_open = false;
}
const tmp_sub_path = std.fmt.hex(af.file_basename_hex);
try af.dir.rename(&tmp_sub_path, af.dir, af.dest_sub_path, io);
af.file_exists = false;
}