From 04a81cd9bcf03d675b6210a631adfd0201d1c1c1 Mon Sep 17 00:00:00 2001 From: "Frank A. Krueger" Date: Fri, 16 Jun 2017 17:33:27 -0700 Subject: [PATCH] Make Children thread safe --- Ooui/Node.cs | 53 +++++++++++++++++++++++++++++--------------- Tests/ButtonTests.cs | 2 ++ 2 files changed, 37 insertions(+), 18 deletions(-) diff --git a/Ooui/Node.cs b/Ooui/Node.cs index dec0e0e..cf19983 100644 --- a/Ooui/Node.cs +++ b/Ooui/Node.cs @@ -8,10 +8,16 @@ namespace Ooui { readonly List children = new List (); - public IEnumerable Children => children; + public IReadOnlyList Children { + get { + lock (children) { + return new List (children).AsReadOnly (); + } + } + } public virtual string Text { - get { return String.Join ("", from c in children select c.Text); } + get { return String.Join ("", from c in Children select c.Text); } set { ReplaceAll (new TextNode (value ?? "")); } @@ -42,18 +48,21 @@ namespace Ooui public Node InsertBefore (Node newChild, Node referenceChild) { - if (referenceChild == null) { - newChild.MessageSent += HandleChildMessageSent; - children.Add (newChild); - } - else { - var index = children.IndexOf (referenceChild); - if (index < 0) { - throw new ArgumentException ("Reference must be a child of this element", nameof (referenceChild)); - } - newChild.MessageSent += HandleChildMessageSent; - children.Insert (index, newChild); + if (newChild == null) + return null; + lock (children) { + if (referenceChild == null) { + children.Add (newChild); + } + else { + var index = children.IndexOf (referenceChild); + if (index < 0) { + throw new ArgumentException ("Reference must be a child of this element", nameof (referenceChild)); + } + children.Insert (index, newChild); + } } + newChild.MessageSent += HandleChildMessageSent; SendCall ("insertBefore", newChild, referenceChild); return newChild; } @@ -62,8 +71,10 @@ namespace Ooui { if (child == null) return null; - if (!children.Remove (child)) { - throw new ArgumentException ("Child not contained in this element", nameof(child)); + lock (children) { + if (!children.Remove (child)) { + throw new ArgumentException ("Child not contained in this element", nameof(child)); + } } child.MessageSent -= HandleChildMessageSent; SendCall ("removeChild", child); @@ -72,9 +83,15 @@ namespace Ooui protected void ReplaceAll (Node newNode) { - var toRemove = new List (children); - foreach (var c in toRemove) - RemoveChild (c); + var toRemove = new List (); + lock (children) { + toRemove.AddRange (children); + children.Clear (); + } + foreach (var child in toRemove) { + child.MessageSent -= HandleChildMessageSent; + SendCall ("removeChild", child); + } InsertBefore (newNode, null); } diff --git a/Tests/ButtonTests.cs b/Tests/ButtonTests.cs index 0361c47..45a1596 100644 --- a/Tests/ButtonTests.cs +++ b/Tests/ButtonTests.cs @@ -12,6 +12,7 @@ namespace Tests public void DefaultCtor () { var b = new Button (); + Assert.AreEqual (0, b.Children.Count); Assert.AreEqual ("button", b.TagName); Assert.AreEqual ("", b.Text); } @@ -20,6 +21,7 @@ namespace Tests public void TextCtor () { var b = new Button ("Hello World!"); + Assert.AreEqual (1, b.Children.Count); Assert.AreEqual ("Hello World!", b.Text); }