| author | |
| committer | |
| log | 4ac36d094c06b04c1c71d972d3f3e1187bccea95 |
| tree | cd1ddefa4e995e899a00cc6c1b7f9dea90ecca96 |
| parent | 73bf897b5cc25ee3f1ec9d0ba1483d779de4b7c3 |
5 files changed, 94 insertions(+), 0 deletions(-)
CMakeLists.txt+3| ... | ... | @@ -415,6 +415,9 @@ set(ZIG_CPP_SOURCES |
| 415 | 415 | |
| 416 | 416 | set(ZIG_STD_FILES |
| 417 | 417 | "array_list.zig" |
| 418 | "atomic/index.zig" | |
| 419 | "atomic/stack.zig" | |
| 420 | "atomic/queue.zig" | |
| 418 | 421 | "base64.zig" |
| 419 | 422 | "buf_map.zig" |
| 420 | 423 | "buf_set.zig" |
std/atomic/index.zig created+7| ... | ... | @@ -0,0 +1,7 @@ |
| 1 | pub const Stack = @import("stack.zig").Stack; | |
| 2 | pub const Queue = @import("queue.zig").Queue; | |
| 3 | ||
| 4 | test "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 | |
| 2 | pub 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 | |
| 2 | pub 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 | 8 | pub const LinkedList = @import("linked_list.zig").LinkedList; |
| 9 | 9 | pub const IntrusiveLinkedList = @import("linked_list.zig").IntrusiveLinkedList; |
| 10 | 10 | |
| 11 | pub const atomic = @import("atomic/index.zig"); | |
| 11 | 12 | pub const base64 = @import("base64.zig"); |
| 12 | 13 | pub const build = @import("build.zig"); |
| 13 | 14 | pub const c = @import("c/index.zig"); |
| ... | ... | @@ -34,6 +35,7 @@ pub const zig = @import("zig/index.zig"); |
| 34 | 35 | |
| 35 | 36 | test "std" { |
| 36 | 37 | // run tests from these |
| 38 | _ = @import("atomic/index.zig"); | |
| 37 | 39 | _ = @import("array_list.zig"); |
| 38 | 40 | _ = @import("buf_map.zig"); |
| 39 | 41 | _ = @import("buf_set.zig"); |