node: use random delays instead of static ones when simulating I/O delay
This commit is contained in:
+66
-23
@@ -11,6 +11,37 @@ const MAX_DESCRIPTORS = 1 << 10;
|
|||||||
const Node = @This();
|
const Node = @This();
|
||||||
const Handle = i32;
|
const Handle = i32;
|
||||||
|
|
||||||
|
const DelayRange = struct {
|
||||||
|
min_us: u64,
|
||||||
|
max_us: u64,
|
||||||
|
};
|
||||||
|
|
||||||
|
const Delay = struct {
|
||||||
|
const dir_close = DelayRange{ .min_us = 2, .max_us = 10 };
|
||||||
|
const dir_create = DelayRange{ .min_us = 20, .max_us = 80 };
|
||||||
|
const dir_delete = DelayRange{ .min_us = 20, .max_us = 80 };
|
||||||
|
const dir_open = DelayRange{ .min_us = 20, .max_us = 80 };
|
||||||
|
const dir_reset = DelayRange{ .min_us = 1, .max_us = 5 };
|
||||||
|
const dir_read = DelayRange{ .min_us = 10, .max_us = 40 };
|
||||||
|
|
||||||
|
const file_create = DelayRange{ .min_us = 20, .max_us = 100 };
|
||||||
|
const file_delete = DelayRange{ .min_us = 20, .max_us = 100 };
|
||||||
|
const file_open = DelayRange{ .min_us = 20, .max_us = 80 };
|
||||||
|
const file_close = DelayRange{ .min_us = 2, .max_us = 15 };
|
||||||
|
const file_size = DelayRange{ .min_us = 2, .max_us = 10 };
|
||||||
|
const file_sync = DelayRange{ .min_us = 150, .max_us = 500 };
|
||||||
|
const file_read = DelayRange{ .min_us = 60, .max_us = 220 };
|
||||||
|
const file_write = DelayRange{ .min_us = 80, .max_us = 300 };
|
||||||
|
const file_seek = DelayRange{ .min_us = 1, .max_us = 8 };
|
||||||
|
|
||||||
|
const socket_listen = DelayRange{ .min_us = 10, .max_us = 40 };
|
||||||
|
const socket_accept_poll = DelayRange{ .min_us = 10, .max_us = 40 };
|
||||||
|
const socket_connect = DelayRange{ .min_us = 50, .max_us = 200 };
|
||||||
|
const socket_read_poll = DelayRange{ .min_us = 10, .max_us = 60 };
|
||||||
|
const socket_write = DelayRange{ .min_us = 20, .max_us = 100 };
|
||||||
|
const socket_close = DelayRange{ .min_us = 5, .max_us = 30 };
|
||||||
|
};
|
||||||
|
|
||||||
pub const TaskID = Scheduler.TaskID;
|
pub const TaskID = Scheduler.TaskID;
|
||||||
const NestedEntryPoint = Scheduler.NestedEntryPoint;
|
const NestedEntryPoint = Scheduler.NestedEntryPoint;
|
||||||
|
|
||||||
@@ -31,6 +62,7 @@ const Descriptor = struct {
|
|||||||
};
|
};
|
||||||
|
|
||||||
gpa: Allocator,
|
gpa: Allocator,
|
||||||
|
prng: *std.Random.DefaultPrng,
|
||||||
local_time: u64,
|
local_time: u64,
|
||||||
arena: std.heap.ArenaAllocator,
|
arena: std.heap.ArenaAllocator,
|
||||||
argv: [][*:0]const u8,
|
argv: [][*:0]const u8,
|
||||||
@@ -80,8 +112,9 @@ fn splitCommandArguments(command: []const u8, arena: Allocator) Allocator.Error!
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn init(self: *Node, real_io: std.Io, scheduler: *Scheduler, network: *Network, command: []const u8, addresses: []const u32, gpa: Allocator) !void {
|
pub fn init(self: *Node, real_io: std.Io, prng: *std.Random.DefaultPrng, scheduler: *Scheduler, network: *Network, command: []const u8, addresses: []const u32, gpa: Allocator) !void {
|
||||||
self.gpa = gpa;
|
self.gpa = gpa;
|
||||||
|
self.prng = prng;
|
||||||
self.local_time = 0;
|
self.local_time = 0;
|
||||||
self.arena = .init(gpa);
|
self.arena = .init(gpa);
|
||||||
self.scheduler = scheduler;
|
self.scheduler = scheduler;
|
||||||
@@ -132,6 +165,16 @@ pub fn sleep(self: *Node, delta_us: u64) !void {
|
|||||||
return self.scheduler.sleep(delta_us);
|
return self.scheduler.sleep(delta_us);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn fakeDelay(self: *Node, range: DelayRange) !void {
|
||||||
|
std.debug.assert(range.min_us <= range.max_us);
|
||||||
|
|
||||||
|
const delay_us = if (range.min_us == range.max_us) range.min_us else blk: {
|
||||||
|
const random = self.prng.random();
|
||||||
|
break :blk range.min_us + random.uintLessThan(u64, range.max_us - range.min_us + 1);
|
||||||
|
};
|
||||||
|
return self.scheduler.sleep(delay_us);
|
||||||
|
}
|
||||||
|
|
||||||
pub fn spawn(self: *Node, entry: NestedEntryPoint, context: *const anyopaque) !TaskID {
|
pub fn spawn(self: *Node, entry: NestedEntryPoint, context: *const anyopaque) !TaskID {
|
||||||
return self.scheduler.spawnNested(self, entry, context);
|
return self.scheduler.spawnNested(self, entry, context);
|
||||||
}
|
}
|
||||||
@@ -220,7 +263,7 @@ fn descToHandle(self: *Node, desc: *Descriptor) Handle {
|
|||||||
pub const CloseDirError = HandleError || CancelError;
|
pub const CloseDirError = HandleError || CancelError;
|
||||||
|
|
||||||
pub fn closeDir(self: *Node, handle: Handle) CloseDirError!void {
|
pub fn closeDir(self: *Node, handle: Handle) CloseDirError!void {
|
||||||
try self.scheduler.sleep(10);
|
try self.fakeDelay(Delay.dir_close);
|
||||||
const desc = try self.handleToDescOfType(handle, .dir);
|
const desc = try self.handleToDescOfType(handle, .dir);
|
||||||
self.file_system.closeDir(&desc.dir, self.gpa);
|
self.file_system.closeDir(&desc.dir, self.gpa);
|
||||||
desc.kind = .unused;
|
desc.kind = .unused;
|
||||||
@@ -229,7 +272,7 @@ pub fn closeDir(self: *Node, handle: Handle) CloseDirError!void {
|
|||||||
pub const CreateDirError = HandleError || FileSystem.CreateError || CancelError;
|
pub const CreateDirError = HandleError || FileSystem.CreateError || CancelError;
|
||||||
|
|
||||||
pub fn createDir(self: *Node, parent: ?Handle, path: []const u8) CreateDirError!void {
|
pub fn createDir(self: *Node, parent: ?Handle, path: []const u8) CreateDirError!void {
|
||||||
try self.scheduler.sleep(10);
|
try self.fakeDelay(Delay.dir_create);
|
||||||
return self.file_system.createDir(path, try self.handleToOpenDirOrNULL(parent), self.gpa);
|
return self.file_system.createDir(path, try self.handleToOpenDirOrNULL(parent), self.gpa);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -238,7 +281,7 @@ pub const OpenDirError = error{
|
|||||||
} || HandleError || FileSystem.OpenError || CancelError;
|
} || HandleError || FileSystem.OpenError || CancelError;
|
||||||
|
|
||||||
pub fn openDir(self: *Node, parent: ?Handle, path: []const u8) OpenDirError!Handle {
|
pub fn openDir(self: *Node, parent: ?Handle, path: []const u8) OpenDirError!Handle {
|
||||||
try self.scheduler.sleep(10);
|
try self.fakeDelay(Delay.dir_open);
|
||||||
const desc = self.unusedDesc() orelse return OpenDirError.DescriptorLimit;
|
const desc = self.unusedDesc() orelse return OpenDirError.DescriptorLimit;
|
||||||
try self.file_system.openDir(path, try self.handleToOpenDirOrNULL(parent), &desc.dir);
|
try self.file_system.openDir(path, try self.handleToOpenDirOrNULL(parent), &desc.dir);
|
||||||
desc.kind = .dir;
|
desc.kind = .dir;
|
||||||
@@ -248,7 +291,7 @@ pub fn openDir(self: *Node, parent: ?Handle, path: []const u8) OpenDirError!Hand
|
|||||||
pub const ResetDirError = HandleError || CancelError;
|
pub const ResetDirError = HandleError || CancelError;
|
||||||
|
|
||||||
pub fn resetDir(self: *Node, handle: Handle) ResetDirError!void {
|
pub fn resetDir(self: *Node, handle: Handle) ResetDirError!void {
|
||||||
try self.scheduler.sleep(2);
|
try self.fakeDelay(Delay.dir_reset);
|
||||||
const desc = try self.handleToDescOfType(handle, .dir);
|
const desc = try self.handleToDescOfType(handle, .dir);
|
||||||
self.file_system.resetDir(&desc.dir);
|
self.file_system.resetDir(&desc.dir);
|
||||||
}
|
}
|
||||||
@@ -256,7 +299,7 @@ pub fn resetDir(self: *Node, handle: Handle) ResetDirError!void {
|
|||||||
pub const ReadDirError = HandleError || FileSystem.ReadDirError || CancelError;
|
pub const ReadDirError = HandleError || FileSystem.ReadDirError || CancelError;
|
||||||
|
|
||||||
pub fn readDir(self: *Node, handle: Handle) ReadDirError!FileSystem.ReadDir {
|
pub fn readDir(self: *Node, handle: Handle) ReadDirError!FileSystem.ReadDir {
|
||||||
try self.scheduler.sleep(10);
|
try self.fakeDelay(Delay.dir_read);
|
||||||
const desc = try self.handleToDescOfType(handle, .dir);
|
const desc = try self.handleToDescOfType(handle, .dir);
|
||||||
return self.file_system.readDir(&desc.dir);
|
return self.file_system.readDir(&desc.dir);
|
||||||
}
|
}
|
||||||
@@ -273,21 +316,21 @@ fn handleToOpenDirOrNULL(self: *Node, handle: ?Handle) HandleError!?*FileSystem.
|
|||||||
pub const CreateFileError = HandleError || FileSystem.CreateError || CancelError;
|
pub const CreateFileError = HandleError || FileSystem.CreateError || CancelError;
|
||||||
|
|
||||||
pub fn createFile(self: *Node, parent: ?Handle, path: []const u8) CreateFileError!void {
|
pub fn createFile(self: *Node, parent: ?Handle, path: []const u8) CreateFileError!void {
|
||||||
try self.scheduler.sleep(10);
|
try self.fakeDelay(Delay.file_create);
|
||||||
return self.file_system.createFile(path, try self.handleToOpenDirOrNULL(parent), self.gpa);
|
return self.file_system.createFile(path, try self.handleToOpenDirOrNULL(parent), self.gpa);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const DeleteFileError = HandleError || FileSystem.DeleteFileError || CancelError;
|
pub const DeleteFileError = HandleError || FileSystem.DeleteFileError || CancelError;
|
||||||
|
|
||||||
pub fn deleteFile(self: *Node, parent: ?Handle, path: []const u8) DeleteFileError!void {
|
pub fn deleteFile(self: *Node, parent: ?Handle, path: []const u8) DeleteFileError!void {
|
||||||
try self.scheduler.sleep(10);
|
try self.fakeDelay(Delay.file_delete);
|
||||||
return self.file_system.deleteFile(path, try self.handleToOpenDirOrNULL(parent), self.gpa);
|
return self.file_system.deleteFile(path, try self.handleToOpenDirOrNULL(parent), self.gpa);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const DeleteDirError = HandleError || FileSystem.DeleteDirError || CancelError;
|
pub const DeleteDirError = HandleError || FileSystem.DeleteDirError || CancelError;
|
||||||
|
|
||||||
pub fn deleteDir(self: *Node, parent: ?Handle, path: []const u8) DeleteDirError!void {
|
pub fn deleteDir(self: *Node, parent: ?Handle, path: []const u8) DeleteDirError!void {
|
||||||
try self.scheduler.sleep(10);
|
try self.fakeDelay(Delay.dir_delete);
|
||||||
return self.file_system.deleteDir(path, try self.handleToOpenDirOrNULL(parent), self.gpa);
|
return self.file_system.deleteDir(path, try self.handleToOpenDirOrNULL(parent), self.gpa);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -296,7 +339,7 @@ pub const OpenFileError = error{
|
|||||||
} || HandleError || FileSystem.OpenError || CancelError;
|
} || HandleError || FileSystem.OpenError || CancelError;
|
||||||
|
|
||||||
pub fn openFile(self: *Node, parent: ?Handle, path: []const u8) OpenFileError!Handle {
|
pub fn openFile(self: *Node, parent: ?Handle, path: []const u8) OpenFileError!Handle {
|
||||||
try self.scheduler.sleep(10);
|
try self.fakeDelay(Delay.file_open);
|
||||||
const desc = self.unusedDesc() orelse return OpenFileError.DescriptorLimit;
|
const desc = self.unusedDesc() orelse return OpenFileError.DescriptorLimit;
|
||||||
try self.file_system.openFile(path, try self.handleToOpenDirOrNULL(parent), &desc.file);
|
try self.file_system.openFile(path, try self.handleToOpenDirOrNULL(parent), &desc.file);
|
||||||
desc.kind = .file;
|
desc.kind = .file;
|
||||||
@@ -306,7 +349,7 @@ pub fn openFile(self: *Node, parent: ?Handle, path: []const u8) OpenFileError!Ha
|
|||||||
pub const CloseFileError = HandleError || CancelError;
|
pub const CloseFileError = HandleError || CancelError;
|
||||||
|
|
||||||
pub fn closeFile(self: *Node, handle: Handle) CloseFileError!void {
|
pub fn closeFile(self: *Node, handle: Handle) CloseFileError!void {
|
||||||
try self.scheduler.sleep(10);
|
try self.fakeDelay(Delay.file_close);
|
||||||
const desc = try self.handleToDescOfType(handle, .file);
|
const desc = try self.handleToDescOfType(handle, .file);
|
||||||
self.file_system.closeFile(&desc.file, self.gpa);
|
self.file_system.closeFile(&desc.file, self.gpa);
|
||||||
desc.kind = .unused;
|
desc.kind = .unused;
|
||||||
@@ -315,7 +358,7 @@ pub fn closeFile(self: *Node, handle: Handle) CloseFileError!void {
|
|||||||
pub const FileSizeError = HandleError || CancelError;
|
pub const FileSizeError = HandleError || CancelError;
|
||||||
|
|
||||||
pub fn fileSize(self: *Node, handle: Handle) FileSizeError!u64 {
|
pub fn fileSize(self: *Node, handle: Handle) FileSizeError!u64 {
|
||||||
try self.scheduler.sleep(2);
|
try self.fakeDelay(Delay.file_size);
|
||||||
const desc = try self.handleToDescOfType(handle, .file);
|
const desc = try self.handleToDescOfType(handle, .file);
|
||||||
return @intCast(self.file_system.fileSize(&desc.file));
|
return @intCast(self.file_system.fileSize(&desc.file));
|
||||||
}
|
}
|
||||||
@@ -323,7 +366,7 @@ pub fn fileSize(self: *Node, handle: Handle) FileSizeError!u64 {
|
|||||||
pub const SyncFileError = HandleError || CancelError;
|
pub const SyncFileError = HandleError || CancelError;
|
||||||
|
|
||||||
pub fn syncFile(self: *Node, handle: Handle) SyncFileError!void {
|
pub fn syncFile(self: *Node, handle: Handle) SyncFileError!void {
|
||||||
try self.scheduler.sleep(2);
|
try self.fakeDelay(Delay.file_sync);
|
||||||
const desc = try self.handleToDescOfType(handle, .file);
|
const desc = try self.handleToDescOfType(handle, .file);
|
||||||
self.file_system.syncFile(&desc.file);
|
self.file_system.syncFile(&desc.file);
|
||||||
}
|
}
|
||||||
@@ -331,7 +374,7 @@ pub fn syncFile(self: *Node, handle: Handle) SyncFileError!void {
|
|||||||
pub const ReadFileError = HandleError || CancelError;
|
pub const ReadFileError = HandleError || CancelError;
|
||||||
|
|
||||||
pub fn readFile(self: *Node, handle: Handle, offset: ?usize, target: []u8) ReadFileError!usize {
|
pub fn readFile(self: *Node, handle: Handle, offset: ?usize, target: []u8) ReadFileError!usize {
|
||||||
try self.scheduler.sleep(100);
|
try self.fakeDelay(Delay.file_read);
|
||||||
if (handle == 0) {
|
if (handle == 0) {
|
||||||
@panic("Not implemented yet"); // TODO: stdin
|
@panic("Not implemented yet"); // TODO: stdin
|
||||||
} else if (handle == 1) {
|
} else if (handle == 1) {
|
||||||
@@ -361,7 +404,7 @@ fn writeToStderr(self: *Node, source: []const u8) void {
|
|||||||
pub const WriteFileError = HandleError || Allocator.Error || CancelError;
|
pub const WriteFileError = HandleError || Allocator.Error || CancelError;
|
||||||
|
|
||||||
pub fn writeFile(self: *Node, handle: Handle, offset: ?usize, header: []const u8, source: []const []const u8) WriteFileError!usize {
|
pub fn writeFile(self: *Node, handle: Handle, offset: ?usize, header: []const u8, source: []const []const u8) WriteFileError!usize {
|
||||||
try self.scheduler.sleep(100);
|
try self.fakeDelay(Delay.file_write);
|
||||||
|
|
||||||
if (handle == 0) {
|
if (handle == 0) {
|
||||||
return HandleError.InvalidHandle;
|
return HandleError.InvalidHandle;
|
||||||
@@ -399,13 +442,13 @@ pub fn writeFile(self: *Node, handle: Handle, offset: ?usize, header: []const u8
|
|||||||
pub const SeekFileError = HandleError || FileSystem.SeekError || CancelError;
|
pub const SeekFileError = HandleError || FileSystem.SeekError || CancelError;
|
||||||
|
|
||||||
pub fn seekFileTo(self: *Node, handle: Handle, offset: usize) SeekFileError!void {
|
pub fn seekFileTo(self: *Node, handle: Handle, offset: usize) SeekFileError!void {
|
||||||
try self.scheduler.sleep(2);
|
try self.fakeDelay(Delay.file_seek);
|
||||||
const desc = try self.handleToDescOfType(handle, .file);
|
const desc = try self.handleToDescOfType(handle, .file);
|
||||||
self.file_system.seekFileTo(&desc.file, offset);
|
self.file_system.seekFileTo(&desc.file, offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn seekFileBy(self: *Node, handle: Handle, offset: i64) SeekFileError!void {
|
pub fn seekFileBy(self: *Node, handle: Handle, offset: i64) SeekFileError!void {
|
||||||
try self.scheduler.sleep(2);
|
try self.fakeDelay(Delay.file_seek);
|
||||||
const desc = try self.handleToDescOfType(handle, .file);
|
const desc = try self.handleToDescOfType(handle, .file);
|
||||||
try self.file_system.seekFileBy(&desc.file, offset);
|
try self.file_system.seekFileBy(&desc.file, offset);
|
||||||
}
|
}
|
||||||
@@ -416,7 +459,7 @@ pub const ListenError = error{
|
|||||||
} || Network.ListenError || CancelError;
|
} || Network.ListenError || CancelError;
|
||||||
|
|
||||||
pub fn listen(self: *Node, address: Address) ListenError!Handle {
|
pub fn listen(self: *Node, address: Address) ListenError!Handle {
|
||||||
try self.scheduler.sleep(10);
|
try self.fakeDelay(Delay.socket_listen);
|
||||||
const desc = self.unusedDesc() orelse return ListenError.DescriptorLimit;
|
const desc = self.unusedDesc() orelse return ListenError.DescriptorLimit;
|
||||||
try self.network_host.listen(address, &desc.listen);
|
try self.network_host.listen(address, &desc.listen);
|
||||||
desc.kind = .listen;
|
desc.kind = .listen;
|
||||||
@@ -432,7 +475,7 @@ pub fn accept(self: *Node, handle: Handle) AcceptError!Handle {
|
|||||||
const new_desc = self.unusedDesc() orelse return AcceptError.DescriptorLimit;
|
const new_desc = self.unusedDesc() orelse return AcceptError.DescriptorLimit;
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
try self.scheduler.sleep(10);
|
try self.fakeDelay(Delay.socket_accept_poll);
|
||||||
self.network_host.accept(&old_desc.listen, &new_desc.conn) catch |err| switch (err) {
|
self.network_host.accept(&old_desc.listen, &new_desc.conn) catch |err| switch (err) {
|
||||||
error.AcceptQueueEmpty => continue,
|
error.AcceptQueueEmpty => continue,
|
||||||
else => return err,
|
else => return err,
|
||||||
@@ -447,7 +490,7 @@ pub const ConnectError = error{
|
|||||||
} || Network.ConnectError || CancelError;
|
} || Network.ConnectError || CancelError;
|
||||||
|
|
||||||
pub fn connect(self: *Node, address: Address) ConnectError!Handle {
|
pub fn connect(self: *Node, address: Address) ConnectError!Handle {
|
||||||
try self.scheduler.sleep(10);
|
try self.fakeDelay(Delay.socket_connect);
|
||||||
const desc = self.unusedDesc() orelse return ConnectError.DescriptorLimit;
|
const desc = self.unusedDesc() orelse return ConnectError.DescriptorLimit;
|
||||||
try self.network_host.connect(address, &desc.conn);
|
try self.network_host.connect(address, &desc.conn);
|
||||||
desc.kind = .conn;
|
desc.kind = .conn;
|
||||||
@@ -464,7 +507,7 @@ pub fn readSocket(self: *Node, handle: Handle, target: []u8, block: bool) ReadSo
|
|||||||
|
|
||||||
if (block) {
|
if (block) {
|
||||||
while (true) {
|
while (true) {
|
||||||
try self.scheduler.sleep(10);
|
try self.fakeDelay(Delay.socket_read_poll);
|
||||||
|
|
||||||
const num = self.network_host.read(&desc.conn, target);
|
const num = self.network_host.read(&desc.conn, target);
|
||||||
|
|
||||||
@@ -485,7 +528,7 @@ pub fn readSocket(self: *Node, handle: Handle, target: []u8, block: bool) ReadSo
|
|||||||
pub const WriteSocketError = HandleError || Network.SendError || CancelError;
|
pub const WriteSocketError = HandleError || Network.SendError || CancelError;
|
||||||
|
|
||||||
pub fn writeSocket(self: *Node, handle: Handle, source: []const u8) WriteSocketError!usize {
|
pub fn writeSocket(self: *Node, handle: Handle, source: []const u8) WriteSocketError!usize {
|
||||||
try self.scheduler.sleep(10);
|
try self.fakeDelay(Delay.socket_write);
|
||||||
const desc = try self.handleToDescOfType(handle, .conn);
|
const desc = try self.handleToDescOfType(handle, .conn);
|
||||||
return self.network_host.send(&desc.conn, source);
|
return self.network_host.send(&desc.conn, source);
|
||||||
}
|
}
|
||||||
@@ -493,7 +536,7 @@ pub fn writeSocket(self: *Node, handle: Handle, source: []const u8) WriteSocketE
|
|||||||
pub const CloseSocketError = HandleError || CancelError;
|
pub const CloseSocketError = HandleError || CancelError;
|
||||||
|
|
||||||
pub fn closeSocket(self: *Node, handle: Handle) CloseSocketError!void {
|
pub fn closeSocket(self: *Node, handle: Handle) CloseSocketError!void {
|
||||||
try self.scheduler.sleep(10);
|
try self.fakeDelay(Delay.socket_close);
|
||||||
const desc = try self.handleToDesc(handle);
|
const desc = try self.handleToDesc(handle);
|
||||||
if (desc.kind == .conn) {
|
if (desc.kind == .conn) {
|
||||||
self.network_host.closeConnSocket(&desc.conn);
|
self.network_host.closeConnSocket(&desc.conn);
|
||||||
|
|||||||
+1
-1
@@ -67,7 +67,7 @@ pub fn spawn(self: *Simulator, command: []const u8, options: SpawnOptions) Spawn
|
|||||||
const node = try self.gpa.create(Node);
|
const node = try self.gpa.create(Node);
|
||||||
errdefer self.gpa.destroy(node);
|
errdefer self.gpa.destroy(node);
|
||||||
|
|
||||||
try node.init(self.real_io, &self.scheduler, &self.network, command, options.addresses, self.gpa);
|
try node.init(self.real_io, &self.prng, &self.scheduler, &self.network, command, options.addresses, self.gpa);
|
||||||
|
|
||||||
try self.nodes.append(self.gpa, node);
|
try self.nodes.append(self.gpa, node);
|
||||||
errdefer _ = self.nodes.swapRemove(self.nodes.items.len-1);
|
errdefer _ = self.nodes.swapRemove(self.nodes.items.len-1);
|
||||||
|
|||||||
Reference in New Issue
Block a user