| 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,6 +415,9 @@ set(ZIG_CPP_SOURCES |
| 415 | 415 | ||
| 416 | set(ZIG_STD_FILES | 416 | set(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 @@ | ||
| 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,6 +8,7 @@ pub const HashMap = @import("hash_map.zig").HashMap; |
| 8 | pub const LinkedList = @import("linked_list.zig").LinkedList; | 8 | pub const LinkedList = @import("linked_list.zig").LinkedList; |
| 9 | pub const IntrusiveLinkedList = @import("linked_list.zig").IntrusiveLinkedList; | 9 | pub const IntrusiveLinkedList = @import("linked_list.zig").IntrusiveLinkedList; |
| 10 | 10 | ||
| 11 | pub const atomic = @import("atomic/index.zig"); | ||
| 11 | pub const base64 = @import("base64.zig"); | 12 | pub const base64 = @import("base64.zig"); |
| 12 | pub const build = @import("build.zig"); | 13 | pub const build = @import("build.zig"); |
| 13 | pub const c = @import("c/index.zig"); | 14 | pub 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"); |
| 34 | 35 | ||
| 35 | test "std" { | 36 | test "std" { |
| 36 | // run tests from these | 37 | // 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"); |