about things
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

add zig 0.15 notes: json serialization, modules, concurrency updates

- json.md: std.json.Stringify patterns, numbers vs strings gotcha
- modules.md: file + directory pattern from ghostty/tigerbeetle
- concurrency.md: background thread shutdown with acquire/release

๐Ÿค– Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

zzstoatzz 3feeaf3a 83c4727d

+158 -2
+1
languages/ziglang/0.15/README.md
··· 21 21 - [crypto](./crypto.md) - ecdsa paths, signature verification 22 22 - [database](./database.md) - zqlite, connection patterns, transactions 23 23 - [interfaces](./interfaces.md) - comptime duck typing, type-returning functions, vtables 24 + - [modules](./modules.md) - file + directory pattern (foo.zig + foo/) 24 25 - [testing](./testing.md) - zig test vs build test, arena for leaky apis
+24 -2
languages/ziglang/0.15/concurrency.md
··· 35 35 36 36 ## memory ordering 37 37 38 - you'll see `.monotonic` everywhere in these projects. it's the weakest ordering - just means "this operation is atomic, but i don't care about ordering relative to other operations." 38 + you'll see `.monotonic` everywhere for counters - it's the weakest ordering, just means "this operation is atomic, but i don't care about ordering relative to other operations." 39 + 40 + use `.acquire`/`.release` when signaling between threads - one thread's write must be visible before another proceeds: 41 + 42 + ```zig 43 + running: std.atomic.Value(bool) = .init(true), 44 + 45 + // main thread: signal shutdown 46 + self.running.store(false, .release); // release: writes before this are visible 47 + if (self.thread) |t| t.join(); 39 48 40 - that's fine for independent counters. you'd use stricter orderings (`.acquire`, `.release`) when one thread's write must be visible to another thread before it proceeds - like signaling that data is ready. none of these projects need that. 49 + // background thread: check for shutdown 50 + fn loop(self: *Self) void { 51 + while (self.running.load(.acquire)) { // acquire: sees writes before store 52 + std.Thread.sleep(interval); 53 + self.doWork(); 54 + } 55 + } 56 + ``` 57 + 58 + rule of thumb: 59 + - independent counters โ†’ `.monotonic` 60 + - signaling (shutdown flags, "data ready" flags) โ†’ `.release` for store, `.acquire` for load 61 + 62 + see: [logfire-zig/root.zig](https://tangled.sh/zzstoatzz.io/logfire-zig/tree/main/src/root.zig) - background flush thread 41 63 42 64 ## callback pattern 43 65
+70
languages/ziglang/0.15/json.md
··· 1 + # json 2 + 3 + building and parsing json. zig 0.15 has `std.json.Stringify` for output and `std.json.parse` for input. 4 + 5 + ## building json 6 + 7 + use `json.Stringify` with a writer. call methods to build the structure incrementally: 8 + 9 + ```zig 10 + const std = @import("std"); 11 + const json = std.json; 12 + 13 + fn buildJson(allocator: std.mem.Allocator, data: MyData) ![]u8 { 14 + var output: std.Io.Writer.Allocating = .init(allocator); 15 + errdefer output.deinit(); 16 + var jw: json.Stringify = .{ .writer = &output.writer }; 17 + 18 + try jw.beginObject(); 19 + try jw.objectField("name"); 20 + try jw.write(data.name); // strings, ints, floats, bools 21 + try jw.objectField("count"); 22 + try jw.write(data.count); 23 + try jw.objectField("items"); 24 + try jw.beginArray(); 25 + for (data.items) |item| { 26 + try jw.write(item); 27 + } 28 + try jw.endArray(); 29 + try jw.endObject(); 30 + 31 + return output.toOwnedSlice(); 32 + } 33 + ``` 34 + 35 + key methods: 36 + - `beginObject()` / `endObject()` - `{` and `}` 37 + - `beginArray()` / `endArray()` - `[` and `]` 38 + - `objectField("key")` - write a key, call `write()` next for the value 39 + - `write(value)` - writes any json-serializable value 40 + 41 + ## raw json passthrough 42 + 43 + when you have a json string that's already valid and want to embed it without re-parsing: 44 + 45 + ```zig 46 + try jw.objectField("nested"); 47 + try jw.beginWriteRaw(); 48 + try jw.writer.writeAll(raw_json_string); 49 + jw.endWriteRaw(); 50 + ``` 51 + 52 + useful when proxying json from external apis. 53 + 54 + ## gotcha: numbers vs strings 55 + 56 + otlp and other protocols care about the difference. timestamps are often strings (to avoid precision loss with large nanosecond values), but counts are numbers: 57 + 58 + ```zig 59 + // timestamp as string 60 + try jw.objectField("timeUnixNano"); 61 + var buf: [32]u8 = undefined; 62 + const s = std.fmt.bufPrint(&buf, "{d}", .{timestamp_ns}) catch unreachable; 63 + try jw.write(s); // "1234567890000000000" 64 + 65 + // count as number 66 + try jw.objectField("count"); 67 + try jw.write(count); // 42 68 + ``` 69 + 70 + see: [logfire-zig/exporter.zig](https://tangled.sh/zzstoatzz.io/logfire-zig/tree/main/src/exporter.zig)
+63
languages/ziglang/0.15/modules.md
··· 1 + # module organization 2 + 3 + patterns for organizing zig modules, derived from ghostty and tigerbeetle. 4 + 5 + ## file + directory pattern 6 + 7 + idiomatic zig uses `foo.zig` alongside `foo/` directory: 8 + 9 + ``` 10 + src/ 11 + โ”œโ”€โ”€ apprt.zig # entry point / public API 12 + โ””โ”€โ”€ apprt/ # implementation files 13 + โ”œโ”€โ”€ action.zig 14 + โ”œโ”€โ”€ structs.zig 15 + โ””โ”€โ”€ gtk.zig 16 + ``` 17 + 18 + the parent file re-exports from the subdirectory: 19 + 20 + ```zig 21 + // apprt.zig 22 + pub const action = @import("apprt/action.zig"); 23 + pub const structs = @import("apprt/structs.zig"); 24 + 25 + pub const Action = action.Action; 26 + pub const Runtime = @import("apprt/runtime.zig").Runtime; 27 + ``` 28 + 29 + no ambiguity because import paths are explicit: 30 + - `@import("apprt.zig")` โ†’ the file (public API) 31 + - `@import("apprt/action.zig")` โ†’ from the directory 32 + 33 + ## anti-patterns 34 + 35 + **don't do `foo/foo.zig`** - redundant naming: 36 + ``` 37 + src/ 38 + โ””โ”€โ”€ orchestration/ 39 + โ””โ”€โ”€ orchestration.zig # wrong 40 + ``` 41 + 42 + **don't do `foo/mod.zig`** - this is rust convention, not zig: 43 + ``` 44 + src/ 45 + โ””โ”€โ”€ orchestration/ 46 + โ””โ”€โ”€ mod.zig # wrong (rust pattern) 47 + ``` 48 + 49 + ## examples in the wild 50 + 51 + ghostty: 52 + - `src/apprt.zig` + `src/apprt/` 53 + - `src/cli.zig` + `src/cli/` 54 + - `src/config.zig` + `src/config/` 55 + 56 + tigerbeetle: 57 + - `src/io.zig` + `src/io/` 58 + - `src/lsm.zig` + `src/lsm/` 59 + 60 + prefect-server: 61 + - `src/orchestration.zig` + `src/orchestration/` 62 + - `src/broker.zig` + `src/broker/` 63 + - `src/services.zig` + `src/services/`