authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-04-27 19:27:58-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-04-28 16:11:32-04:00
log4ac36d094c06b04c1c71d972d3f3e1187bccea95
treecd1ddefa4e995e899a00cc6c1b7f9dea90ecca96
parent73bf897b5cc25ee3f1ec9d0ba1483d779de4b7c3

add std.atomic.Stack and std.atomic.Queue


5 files changed, 94 insertions(+), 0 deletions(-)

CMakeLists.txt+3
...@@ -415,6 +415,9 @@ set(ZIG_CPP_SOURCES...@@ -415,6 +415,9 @@ set(ZIG_CPP_SOURCES
415415
416set(ZIG_STD_FILES416set(ZIG_STD_FILES
417 "array_list.zig"417 "array_list.zig"
418 "atomic/index.zig"
419 "atomic/stack.zig"
420 "atomic/queue.zig"
418 "base64.zig"421 "base64.zig"
419 "buf_map.zig"422 "buf_map.zig"
420 "buf_set.zig"423 "buf_set.zig"
std/atomic/index.zig created+7
...@@ -0,0 +1,7 @@
1pub const Stack = @import("stack.zig").Stack;
2pub const Queue = @import("queue.zig").Queue;
3
4test "std.atomic" {
5 _ = @import("stack.zig").Stack;
6 _ = @import("queue.zig").Queue;
7}
std/atomic/queue.zig created+37
...@@ -0,0 +1,37 @@
1/// Many reader, many writer, non-allocating, thread-safe, lock-free
2pub fn Queue(comptime T: type) type {
3 return struct {
4 head: &Node,
5 tail: &Node,
6 root: Node,
7
8 pub const Self = this;
9
10 pub const Node = struct {
11 next: ?&Node,
12 data: T,
13 };
14
15 // TODO: well defined copy elision
16 pub fn init(self: &Self) void {
17 self.root.next = null;
18 self.head = &self.root;
19 self.tail = &self.root;
20 }
21
22 pub fn put(self: &Self, node: &Node) void {
23 node.next = null;
24
25 const tail = @atomicRmw(&Node, &self.tail, AtomicRmwOp.Xchg, node, AtomicOrder.SeqCst);
26 _ = @atomicRmw(?&Node, &tail.next, AtomicRmwOp.Xchg, node, AtomicOrder.SeqCst);
27 }
28
29 pub fn get(self: &Self) ?&Node {
30 var head = @atomicLoad(&Node, &self.head, AtomicOrder.Acquire);
31 while (true) {
32 const node = head.next ?? return null;
33 head = @cmpxchgWeak(&Node, &self.head, head, node, AtomicOrder.Release, AtomicOrder.Acquire) ?? return node;
34 }
35 }
36 };
37}
std/atomic/stack.zig created+45
...@@ -0,0 +1,45 @@
1/// Many reader, many writer, non-allocating, thread-safe, lock-free
2pub fn Stack(comptime T: type) type {
3 return struct {
4 root: ?&Node,
5
6 pub const Self = this;
7
8 pub const Node = struct {
9 next: ?&Node,
10 data: T,
11 };
12
13 pub fn init() Self {
14 return Self {
15 .root = null,
16 };
17 }
18
19 /// push operation, but only if you are the first item in the stack. if you did not succeed in
20 /// being the first item in the stack, returns the other item that was there.
21 pub fn pushFirst(self: &Self, node: &Node) ?&Node {
22 node.next = null;
23 return @cmpxchgStrong(?&Node, &self.root, null, node, AtomicOrder.AcqRel, AtomicOrder.AcqRel);
24 }
25
26 pub fn push(self: &Self, node: &Node) void {
27 var root = @atomicLoad(?&Node, &self.root, AtomicOrder.Acquire);
28 while (true) {
29 node.next = root;
30 root = @cmpxchgWeak(?&Node, &self.root, root, node, AtomicOrder.Release, AtomicOrder.Acquire) ?? break;
31 }
32 }
33
34 pub fn pop(self: &Self) ?&Node {
35 var root = @atomicLoad(?&Node, &self.root, AtomicOrder.Acquire);
36 while (true) {
37 root = @cmpxchgWeak(?&Node, &self.root, root, (root ?? return null).next, AtomicOrder.Release, AtomicOrder.Acquire) ?? return root;
38 }
39 }
40
41 pub fn isEmpty(self: &Self) bool {
42 return @atomicLoad(?&Node, &self.root, AtomicOrder.Relaxed) == null;
43 }
44 };
45}
std/index.zig+2
...@@ -8,6 +8,7 @@ pub const HashMap = @import("hash_map.zig").HashMap;...@@ -8,6 +8,7 @@ pub const HashMap = @import("hash_map.zig").HashMap;
8pub const LinkedList = @import("linked_list.zig").LinkedList;8pub const LinkedList = @import("linked_list.zig").LinkedList;
9pub const IntrusiveLinkedList = @import("linked_list.zig").IntrusiveLinkedList;9pub const IntrusiveLinkedList = @import("linked_list.zig").IntrusiveLinkedList;
1010
11pub const atomic = @import("atomic/index.zig");
11pub const base64 = @import("base64.zig");12pub const base64 = @import("base64.zig");
12pub const build = @import("build.zig");13pub const build = @import("build.zig");
13pub const c = @import("c/index.zig");14pub const c = @import("c/index.zig");
...@@ -34,6 +35,7 @@ pub const zig = @import("zig/index.zig");...@@ -34,6 +35,7 @@ pub const zig = @import("zig/index.zig");
3435
35test "std" {36test "std" {
36 // run tests from these37 // run tests from these
38 _ = @import("atomic/index.zig");
37 _ = @import("array_list.zig");39 _ = @import("array_list.zig");
38 _ = @import("buf_map.zig");40 _ = @import("buf_map.zig");
39 _ = @import("buf_set.zig");41 _ = @import("buf_set.zig");