diff --git a/src/bson.zig b/src/bson.zig index 35b57ab..2dd3828 100644 --- a/src/bson.zig +++ b/src/bson.zig @@ -494,12 +494,16 @@ fn copy_values(arena: std.mem.Allocator, items: []const Value) std.mem.Allocator pub const ObjectIdGen = struct { random_prefix: [5]u8, - counter: u32, + // Atomic so concurrent connections (e.g. two hellos, or a hello racing + // an insert) can share one generator without a data race. The counter + // only needs uniqueness within a second + random prefix, so monotonic + // fetchAdd is fine. + counter: std.atomic.Value(u32), pub fn init(io: std.Io) ObjectIdGen { var self: ObjectIdGen = undefined; io.random(&self.random_prefix); - self.counter = 0; + self.counter = .init(0); return self; } @@ -509,8 +513,8 @@ pub const ObjectIdGen = struct { const secs: u32 = @truncate(@as(u64, @intCast(now.toSeconds()))); std.mem.writeInt(u32, oid[0..4], secs, .big); @memcpy(oid[4..9], &self.random_prefix); - self.counter +%= 1; - std.mem.writeInt(u24, oid[9..12], @truncate(self.counter), .big); + const n = self.counter.fetchAdd(1, .monotonic) +% 1; + std.mem.writeInt(u24, oid[9..12], @truncate(n), .big); return oid; } };