Make Children thread safe

This commit is contained in:
Frank A. Krueger 2017-06-16 17:33:27 -07:00
parent 84ee2e9785
commit 04a81cd9bc
2 changed files with 37 additions and 18 deletions

View File

@ -8,10 +8,16 @@ namespace Ooui
{ {
readonly List<Node> children = new List<Node> (); readonly List<Node> children = new List<Node> ();
public IEnumerable<Node> Children => children; public IReadOnlyList<Node> Children {
get {
lock (children) {
return new List<Node> (children).AsReadOnly ();
}
}
}
public virtual string Text { 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 { set {
ReplaceAll (new TextNode (value ?? "")); ReplaceAll (new TextNode (value ?? ""));
} }
@ -42,18 +48,21 @@ namespace Ooui
public Node InsertBefore (Node newChild, Node referenceChild) public Node InsertBefore (Node newChild, Node referenceChild)
{ {
if (referenceChild == null) { if (newChild == null)
newChild.MessageSent += HandleChildMessageSent; return null;
children.Add (newChild); lock (children) {
} if (referenceChild == null) {
else { children.Add (newChild);
var index = children.IndexOf (referenceChild); }
if (index < 0) { else {
throw new ArgumentException ("Reference must be a child of this element", nameof (referenceChild)); var index = children.IndexOf (referenceChild);
} if (index < 0) {
newChild.MessageSent += HandleChildMessageSent; throw new ArgumentException ("Reference must be a child of this element", nameof (referenceChild));
children.Insert (index, newChild); }
children.Insert (index, newChild);
}
} }
newChild.MessageSent += HandleChildMessageSent;
SendCall ("insertBefore", newChild, referenceChild); SendCall ("insertBefore", newChild, referenceChild);
return newChild; return newChild;
} }
@ -62,8 +71,10 @@ namespace Ooui
{ {
if (child == null) if (child == null)
return null; return null;
if (!children.Remove (child)) { lock (children) {
throw new ArgumentException ("Child not contained in this element", nameof(child)); if (!children.Remove (child)) {
throw new ArgumentException ("Child not contained in this element", nameof(child));
}
} }
child.MessageSent -= HandleChildMessageSent; child.MessageSent -= HandleChildMessageSent;
SendCall ("removeChild", child); SendCall ("removeChild", child);
@ -72,9 +83,15 @@ namespace Ooui
protected void ReplaceAll (Node newNode) protected void ReplaceAll (Node newNode)
{ {
var toRemove = new List<Node> (children); var toRemove = new List<Node> ();
foreach (var c in toRemove) lock (children) {
RemoveChild (c); toRemove.AddRange (children);
children.Clear ();
}
foreach (var child in toRemove) {
child.MessageSent -= HandleChildMessageSent;
SendCall ("removeChild", child);
}
InsertBefore (newNode, null); InsertBefore (newNode, null);
} }

View File

@ -12,6 +12,7 @@ namespace Tests
public void DefaultCtor () public void DefaultCtor ()
{ {
var b = new Button (); var b = new Button ();
Assert.AreEqual (0, b.Children.Count);
Assert.AreEqual ("button", b.TagName); Assert.AreEqual ("button", b.TagName);
Assert.AreEqual ("", b.Text); Assert.AreEqual ("", b.Text);
} }
@ -20,6 +21,7 @@ namespace Tests
public void TextCtor () public void TextCtor ()
{ {
var b = new Button ("Hello World!"); var b = new Button ("Hello World!");
Assert.AreEqual (1, b.Children.Count);
Assert.AreEqual ("Hello World!", b.Text); Assert.AreEqual ("Hello World!", b.Text);
} }