Commit e190082922

Shawn Landden <shawn@git.icu>
2020-01-19 19:08:05
rb: *breaking* make API thread-safe
use @fieldParentPtr to access your context fields, which lie if you struct that contains a rb.Tree member (without a pointer). Also simplifies the init() function so rb.Tree can be initialized in a single line, without having to use "undefined".
1 parent de07ca7
Changed files (1)
lib
std
lib/std/rb.zig
@@ -132,7 +132,7 @@ pub const Node = struct {
 
 pub const Tree = struct {
     root: ?*Node,
-    compareFn: fn (*Node, *Node) Order,
+    compareFn: fn (*Node, *Node, *Tree) Order,
 
     /// If you have a need for a version that caches this, please file a bug.
     pub fn first(tree: *Tree) ?*Node {
@@ -389,7 +389,7 @@ pub const Tree = struct {
         var new = newconst;
 
         // I assume this can get optimized out if the caller already knows.
-        if (tree.compareFn(old, new) != .eq) return ReplaceError.NotEqual;
+        if (tree.compareFn(old, new, tree) != .eq) return ReplaceError.NotEqual;
 
         if (old.getParent()) |parent| {
             parent.setChild(new, parent.left == old);
@@ -404,9 +404,11 @@ pub const Tree = struct {
         new.* = old.*;
     }
 
-    pub fn init(tree: *Tree, f: fn (*Node, *Node) Order) void {
-        tree.root = null;
-        tree.compareFn = f;
+    pub fn init(f: fn (*Node, *Node, *Tree) Order) Tree {
+        return Tree{
+            .root = null,
+            .compareFn = f,
+        };
     }
 };
 
@@ -469,7 +471,7 @@ fn doLookup(key: *Node, tree: *Tree, pparent: *?*Node, is_left: *bool) ?*Node {
     is_left.* = false;
 
     while (maybe_node) |node| {
-        const res = tree.compareFn(node, key);
+        const res = tree.compareFn(node, key, tree);
         if (res == .eq) {
             return node;
         }
@@ -498,7 +500,7 @@ fn testGetNumber(node: *Node) *testNumber {
     return @fieldParentPtr(testNumber, "node", node);
 }
 
-fn testCompare(l: *Node, r: *Node) Order {
+fn testCompare(l: *Node, r: *Node, contextIgnored: *Tree) Order {
     var left = testGetNumber(l);
     var right = testGetNumber(r);
 
@@ -518,7 +520,7 @@ test "rb" {
         return error.SkipZigTest;
     }
 
-    var tree: Tree = undefined;
+    var tree = Tree.init(testCompare);
     var ns: [10]testNumber = undefined;
     ns[0].value = 42;
     ns[1].value = 41;
@@ -534,7 +536,6 @@ test "rb" {
     var dup: testNumber = undefined;
     dup.value = 32345;
 
-    tree.init(testCompare);
     _ = tree.insert(&ns[1].node);
     _ = tree.insert(&ns[2].node);
     _ = tree.insert(&ns[3].node);
@@ -557,8 +558,7 @@ test "rb" {
 }
 
 test "inserting and looking up" {
-    var tree: Tree = undefined;
-    tree.init(testCompare);
+    var tree = Tree.init(testCompare);
     var number: testNumber = undefined;
     number.value = 1000;
     _ = tree.insert(&number.node);
@@ -582,8 +582,7 @@ test "multiple inserts, followed by calling first and last" {
         // TODO https://github.com/ziglang/zig/issues/3288
         return error.SkipZigTest;
     }
-    var tree: Tree = undefined;
-    tree.init(testCompare);
+    var tree = Tree.init(testCompare);
     var zeroth: testNumber = undefined;
     zeroth.value = 0;
     var first: testNumber = undefined;