mirror of
https://github.com/ziglang/zig.git
synced 2024-11-15 00:26:57 +00:00
add std.atomic.Stack and std.atomic.Queue
This commit is contained in:
parent
73bf897b5c
commit
4ac36d094c
@ -415,6 +415,9 @@ set(ZIG_CPP_SOURCES
|
||||
|
||||
set(ZIG_STD_FILES
|
||||
"array_list.zig"
|
||||
"atomic/index.zig"
|
||||
"atomic/stack.zig"
|
||||
"atomic/queue.zig"
|
||||
"base64.zig"
|
||||
"buf_map.zig"
|
||||
"buf_set.zig"
|
||||
|
7
std/atomic/index.zig
Normal file
7
std/atomic/index.zig
Normal file
@ -0,0 +1,7 @@
|
||||
pub const Stack = @import("stack.zig").Stack;
|
||||
pub const Queue = @import("queue.zig").Queue;
|
||||
|
||||
test "std.atomic" {
|
||||
_ = @import("stack.zig").Stack;
|
||||
_ = @import("queue.zig").Queue;
|
||||
}
|
37
std/atomic/queue.zig
Normal file
37
std/atomic/queue.zig
Normal file
@ -0,0 +1,37 @@
|
||||
/// Many reader, many writer, non-allocating, thread-safe, lock-free
|
||||
pub fn Queue(comptime T: type) type {
|
||||
return struct {
|
||||
head: &Node,
|
||||
tail: &Node,
|
||||
root: Node,
|
||||
|
||||
pub const Self = this;
|
||||
|
||||
pub const Node = struct {
|
||||
next: ?&Node,
|
||||
data: T,
|
||||
};
|
||||
|
||||
// TODO: well defined copy elision
|
||||
pub fn init(self: &Self) void {
|
||||
self.root.next = null;
|
||||
self.head = &self.root;
|
||||
self.tail = &self.root;
|
||||
}
|
||||
|
||||
pub fn put(self: &Self, node: &Node) void {
|
||||
node.next = null;
|
||||
|
||||
const tail = @atomicRmw(&Node, &self.tail, AtomicRmwOp.Xchg, node, AtomicOrder.SeqCst);
|
||||
_ = @atomicRmw(?&Node, &tail.next, AtomicRmwOp.Xchg, node, AtomicOrder.SeqCst);
|
||||
}
|
||||
|
||||
pub fn get(self: &Self) ?&Node {
|
||||
var head = @atomicLoad(&Node, &self.head, AtomicOrder.Acquire);
|
||||
while (true) {
|
||||
const node = head.next ?? return null;
|
||||
head = @cmpxchgWeak(&Node, &self.head, head, node, AtomicOrder.Release, AtomicOrder.Acquire) ?? return node;
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
45
std/atomic/stack.zig
Normal file
45
std/atomic/stack.zig
Normal file
@ -0,0 +1,45 @@
|
||||
/// Many reader, many writer, non-allocating, thread-safe, lock-free
|
||||
pub fn Stack(comptime T: type) type {
|
||||
return struct {
|
||||
root: ?&Node,
|
||||
|
||||
pub const Self = this;
|
||||
|
||||
pub const Node = struct {
|
||||
next: ?&Node,
|
||||
data: T,
|
||||
};
|
||||
|
||||
pub fn init() Self {
|
||||
return Self {
|
||||
.root = null,
|
||||
};
|
||||
}
|
||||
|
||||
/// push operation, but only if you are the first item in the stack. if you did not succeed in
|
||||
/// being the first item in the stack, returns the other item that was there.
|
||||
pub fn pushFirst(self: &Self, node: &Node) ?&Node {
|
||||
node.next = null;
|
||||
return @cmpxchgStrong(?&Node, &self.root, null, node, AtomicOrder.AcqRel, AtomicOrder.AcqRel);
|
||||
}
|
||||
|
||||
pub fn push(self: &Self, node: &Node) void {
|
||||
var root = @atomicLoad(?&Node, &self.root, AtomicOrder.Acquire);
|
||||
while (true) {
|
||||
node.next = root;
|
||||
root = @cmpxchgWeak(?&Node, &self.root, root, node, AtomicOrder.Release, AtomicOrder.Acquire) ?? break;
|
||||
}
|
||||
}
|
||||
|
||||
pub fn pop(self: &Self) ?&Node {
|
||||
var root = @atomicLoad(?&Node, &self.root, AtomicOrder.Acquire);
|
||||
while (true) {
|
||||
root = @cmpxchgWeak(?&Node, &self.root, root, (root ?? return null).next, AtomicOrder.Release, AtomicOrder.Acquire) ?? return root;
|
||||
}
|
||||
}
|
||||
|
||||
pub fn isEmpty(self: &Self) bool {
|
||||
return @atomicLoad(?&Node, &self.root, AtomicOrder.Relaxed) == null;
|
||||
}
|
||||
};
|
||||
}
|
@ -8,6 +8,7 @@ pub const HashMap = @import("hash_map.zig").HashMap;
|
||||
pub const LinkedList = @import("linked_list.zig").LinkedList;
|
||||
pub const IntrusiveLinkedList = @import("linked_list.zig").IntrusiveLinkedList;
|
||||
|
||||
pub const atomic = @import("atomic/index.zig");
|
||||
pub const base64 = @import("base64.zig");
|
||||
pub const build = @import("build.zig");
|
||||
pub const c = @import("c/index.zig");
|
||||
@ -34,6 +35,7 @@ pub const zig = @import("zig/index.zig");
|
||||
|
||||
test "std" {
|
||||
// run tests from these
|
||||
_ = @import("atomic/index.zig");
|
||||
_ = @import("array_list.zig");
|
||||
_ = @import("buf_map.zig");
|
||||
_ = @import("buf_set.zig");
|
||||
|
Loading…
Reference in New Issue
Block a user