bson: make ObjectIdGen counter atomic for concurrent connections
This commit is contained in:
12
src/bson.zig
12
src/bson.zig
@@ -494,12 +494,16 @@ fn copy_values(arena: std.mem.Allocator, items: []const Value) std.mem.Allocator
|
|||||||
|
|
||||||
pub const ObjectIdGen = struct {
|
pub const ObjectIdGen = struct {
|
||||||
random_prefix: [5]u8,
|
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 {
|
pub fn init(io: std.Io) ObjectIdGen {
|
||||||
var self: ObjectIdGen = undefined;
|
var self: ObjectIdGen = undefined;
|
||||||
io.random(&self.random_prefix);
|
io.random(&self.random_prefix);
|
||||||
self.counter = 0;
|
self.counter = .init(0);
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -509,8 +513,8 @@ pub const ObjectIdGen = struct {
|
|||||||
const secs: u32 = @truncate(@as(u64, @intCast(now.toSeconds())));
|
const secs: u32 = @truncate(@as(u64, @intCast(now.toSeconds())));
|
||||||
std.mem.writeInt(u32, oid[0..4], secs, .big);
|
std.mem.writeInt(u32, oid[0..4], secs, .big);
|
||||||
@memcpy(oid[4..9], &self.random_prefix);
|
@memcpy(oid[4..9], &self.random_prefix);
|
||||||
self.counter +%= 1;
|
const n = self.counter.fetchAdd(1, .monotonic) +% 1;
|
||||||
std.mem.writeInt(u24, oid[9..12], @truncate(self.counter), .big);
|
std.mem.writeInt(u24, oid[9..12], @truncate(n), .big);
|
||||||
return oid;
|
return oid;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user