Quick Reference
A compact lookup for “how do I do X in Volt?” Copy-paste the pattern you need.
Starting the Runtime
Section titled “Starting the Runtime”const volt = @import("volt");
// Zero-config (auto worker count, page allocator)pub fn main() !void { try volt.run(myApp);}
// Custom configpub fn main() !void { try volt.runWith(allocator, .{ .num_workers = 4, .max_blocking_threads = 128, }, myApp);}
// Explicit (full control, recommended for production)pub fn main() !void { var io = try volt.Io.init(allocator, .{ .num_workers = 4 }); defer io.deinit(); try io.run(myApp);}
fn myApp(io: volt.Io) void { // All Volt APIs available here _ = io;}Spawning Tasks
Section titled “Spawning Tasks”| Pattern | Code |
|---|---|
| Spawn + await | var f = try io.@"async"(fn, .{args}); const result = f.@"await"(io); |
| Fire-and-forget | _ = try io.@"async"(fn, .{args}); |
| Blocking pool | var f = try io.concurrent(fn, .{args}); const result = try f.@"await"(io); |
| Group (structured) | var g = volt.Group.init(io); _ = g.spawn(fn, .{args}); g.wait(); |
| Cancel | f.cancel(io); or g.cancel(); |
Sync Primitives
Section titled “Sync Primitives”| Primitive | Create | Try (no runtime) | Convenience (needs io) | Release |
|---|---|---|---|---|
| Mutex | var m = volt.sync.Mutex.init(); | if (m.tryLock()) { ... } | m.lock(io); | m.unlock(); |
| RwLock | var rw = volt.sync.RwLock.init(); | if (rw.tryReadLock()) { ... } | rw.readLock(io); | rw.readUnlock(); |
if (rw.tryWriteLock()) { ... } | rw.writeLock(io); | rw.writeUnlock(); | ||
| Semaphore | var s = volt.sync.Semaphore.init(n); | if (s.tryAcquire(1)) { ... } | s.acquire(io, 1); | s.release(1); |
| Notify | var n = volt.sync.Notify.init(); | — | n.wait(io); | n.notifyOne(); / n.notifyAll(); |
| Barrier | var b = volt.sync.Barrier.init(n); | — | b.wait(io); | (auto-releases) |
| OnceCell | var o = volt.sync.OnceCell(T).init(); | o.get() | o.getOrInit(io, initFn) | — |
All sync primitives are zero-allocation. No deinit() needed.
Channels
Section titled “Channels”| Type | Create | deinit? | Send | Receive |
|---|---|---|---|---|
| Channel | var ch = try volt.channel.bounded(T, alloc, cap); | Yes | ch.trySend(val) / ch.send(io, val) | ch.tryRecv() / ch.recv(io) |
| Oneshot | var os = volt.channel.oneshot(T); | No | _ = os.sender.send(val); | os.receiver.tryRecv() / os.receiver.recv(io) |
| Broadcast | var bc = try volt.channel.broadcast(T, alloc, cap); | Yes | _ = bc.send(val); | rx.tryRecv() / rx.recv(io) |
| Watch | var wt = volt.channel.watch(T, initial); | No | wt.send(val); | rx.borrow() / rx.changed(io) |
Rule: if you passed an allocator, you must defer ch.deinit().
Networking
Section titled “Networking”Bind and accept
Section titled “Bind and accept”var listener = try volt.net.listen("0.0.0.0:8080");defer listener.close();
while (true) { if (try listener.tryAccept()) |result| { var stream = result.stream; _ = io.@"async"(handle, .{stream}) catch continue; }}Connect
Section titled “Connect”var stream = try volt.net.connect("127.0.0.1:8080");defer stream.close();
// With DNSvar stream2 = try volt.net.connectHost(allocator, "example.com", 443);defer stream2.close();Read template (handle all four outcomes)
Section titled “Read template (handle all four outcomes)”const n = stream.tryRead(&buf) catch return orelse continue;if (n == 0) return; // Peer closedprocessData(buf[0..n]);stream.writeAll(data) catch return;var sock = try volt.net.UdpSocket.bind(volt.net.Address.fromPort(8080));defer sock.close();
if (try sock.tryRecvFrom(&buf)) |result| { _ = try sock.trySendTo(result.data, result.addr);}Timers
Section titled “Timers”// Duration constructorsconst d1 = volt.Duration.fromSecs(5);const d2 = volt.Duration.fromMillis(100);const d3 = volt.Duration.fromNanos(1000);
// Create a sleep (use with timer driver or poll manually)var slp = volt.time.sleep(volt.Duration.fromSecs(1));// For blocking contexts (non-async):volt.time.blockingSleep(volt.Duration.fromSecs(1));
// Instant (monotonic clock)const start = volt.time.Instant.now();// ... do work ...const elapsed = start.elapsed();Signals and Shutdown
Section titled “Signals and Shutdown”// Wait for Ctrl+Cvolt.signal.waitForCtrlC();
// Graceful shutdownvar shutdown = try volt.shutdown.Shutdown.init();defer shutdown.deinit();
while (!shutdown.isShutdown()) { // ... accept connections ...}
// Wait for in-flight work_ = shutdown.waitPendingTimeout(volt.Duration.fromSecs(5));Key Rules
Section titled “Key Rules”-
iomeans async. If a function takesio: volt.Io, it yields the task (safe on worker threads). If it doesn’t takeioand does I/O, it blocks the thread. -
Allocator means
deinit(). If you passed an allocator to create it (Channel,BroadcastChannel),defer x.deinit(). Everything else is zero-allocation. -
Use
varfor futures. Futures are mutated during polling.constwon’t compile. -
Handle all four I/O outcomes.
tryReadreturns: data (n > 0), would-block (null), peer-close (n == 0), error. Don’t skip any. -
Don’t block worker threads. No
std.Thread.sleep, no CPU loops, no sync file I/O. Useio.concurrent()for blocking work,volt.time.sleep()for delays.
See Common Pitfalls for detailed explanations of each footgun with bad/good code pairs.