aboutsummaryrefslogtreecommitdiffstatsci
path: root/src/GraphicObjects
diff options
context:
space:
mode:
authorJean-Philippe Bruyère <jp_bruyere@hotmail.com>2018-02-21 16:11:30 +0100
committerJean-Philippe Bruyère <jp_bruyere@hotmail.com>2018-02-21 16:11:30 +0100
commit05e7cd5133826afd42d215e08c4874ee48ed49be (patch)
tree2f449777278cc8b4805a4e80d7ee81b3863bc4a1 /src/GraphicObjects
parent30b49efa1763ebdfe82f9d69e0e7bafcdd3b25a8 (diff)
implement ReaderWritelLockSlim to resolve threading issues
Diffstat (limited to 'src/GraphicObjects')
-rw-r--r--src/GraphicObjects/Docker.cs14
-rw-r--r--src/GraphicObjects/GraphicObject.cs43
-rw-r--r--src/GraphicObjects/Group.cs125
-rw-r--r--src/GraphicObjects/TabView.cs21
-rw-r--r--src/GraphicObjects/Wrapper.cs80
5 files changed, 168 insertions, 115 deletions
diff --git a/src/GraphicObjects/Docker.cs b/src/GraphicObjects/Docker.cs
index 3b66eb7e..c52c094f 100644
--- a/src/GraphicObjects/Docker.cs
+++ b/src/GraphicObjects/Docker.cs
@@ -146,14 +146,16 @@ namespace Crow
gr.Clip ();
}
- lock (Children) {
- foreach (GraphicObject g in Children) {
- if (CurrentInterface.DragAndDropOperation?.DragSource == g)
- continue;
- g.Paint (ref gr);
- }
+ childrenRWLock.EnterReadLock ();
+
+ foreach (GraphicObject g in Children) {
+ if (CurrentInterface.DragAndDropOperation?.DragSource == g)
+ continue;
+ g.Paint (ref gr);
}
+ childrenRWLock.ExitReadLock ();
+
if (showDockingTarget) {
Rectangle r;
if (mainStack == null)
diff --git a/src/GraphicObjects/GraphicObject.cs b/src/GraphicObjects/GraphicObject.cs
index d49cbe8f..f671239d 100644
--- a/src/GraphicObjects/GraphicObject.cs
+++ b/src/GraphicObjects/GraphicObject.cs
@@ -34,6 +34,7 @@ using System.Runtime.CompilerServices;
using Cairo;
using System.Diagnostics;
using Crow.IML;
+using System.Threading;
namespace Crow
{
@@ -42,6 +43,8 @@ namespace Crow
/// </summary>
public class GraphicObject : ILayoutable, IValueChange, IDisposable
{
+ internal ReaderWriterLockSlim parentRWLock = new ReaderWriterLockSlim();
+
#region IDisposable implementation
protected bool disposed = false;
@@ -66,6 +69,7 @@ namespace Crow
if (IsQueueForRedraw)
throw new Exception("Trying to dispose an object queued for Redraw: " + this.ToString());
#endif
+
if (CurrentInterface.HoverWidget != null) {
if (CurrentInterface.HoverWidget.IsOrIsInside(this))
CurrentInterface.HoverWidget = null;
@@ -80,13 +84,15 @@ namespace Crow
}
if (!localDataSourceIsNull)
DataSource = null;
+
+ parentRWLock.EnterWriteLock();
parent = null;
+ parentRWLock.ExitWriteLock();
} else
Debug.WriteLine ("!!! Finalized by GC: {0}", this.ToString ());
Clipping?.Dispose ();
bmp?.Dispose ();
disposed = true;
-
}
#endregion
@@ -217,7 +223,7 @@ namespace Crow
//TODO: we should ensure the whole parsed widget tree is the last painted
public Rectangle LastPaintedSlot;
/// <summary>Prevent requeuing multiple times the same widget</summary>
- public bool IsQueueForRedraw = false;
+ public bool IsQueueForClipping = false;
/// <summary>drawing Cache, if null, a redraw is done, cached or not</summary>
public Surface bmp;
public bool IsDirty = true;
@@ -243,11 +249,12 @@ namespace Crow
if (parent == value)
return;
DataSourceChangeEventArgs e = new DataSourceChangeEventArgs (parent, value);
- lock (CurrentInterface.LayoutMutex) {
- parent = value;
- }
- onParentChanged (this, e);
-
+
+ parentRWLock.EnterWriteLock();
+ parent = value;
+ parentRWLock.ExitWriteLock();
+
+ onParentChanged (this, e);
}
}
[XmlIgnore]public ILayoutable LogicalParent {
@@ -774,7 +781,7 @@ namespace Crow
/// Seek first logical tree upward if logicalParent is set, or seek graphic tree for
/// a not null dataSource that will be active for all descendants having dataSource=null
/// </summary>
- [XmlAttributeAttribute]//[DefaultValue(null)]
+ [XmlAttributeAttribute]
public virtual object DataSource {
set {
if (DataSource == value)
@@ -784,12 +791,11 @@ namespace Crow
dataSource = value;
dse.NewDataSource = DataSource;
- //prevent setting null causing stack overflow in specific case
if (dse.NewDataSource == dse.OldDataSource)
return;
- lock (CurrentInterface.LayoutMutex) {
- OnDataSourceChanged (this, dse);
- }
+
+ OnDataSourceChanged (this, dse);
+
NotifyValueChanged ("DataSource", DataSource);
}
@@ -854,9 +860,9 @@ namespace Crow
/// <summary> Loads the default values from XML attributes default </summary>
public void loadDefaultValues()
{
- #if DEBUG_LOAD
- Debug.WriteLine ("LoadDefValues for " + this.ToString ());
- #endif
+// #if DEBUG_LOAD
+// Debug.WriteLine ("LoadDefValues for " + this.ToString ());
+// #endif
Type thisType = this.GetType ();
@@ -1138,13 +1144,12 @@ namespace Crow
#if DEBUG_UPDATE
Debug.WriteLine (string.Format("ClippingRegistration -> {0}", this.ToString ()));
#endif
- lock(CurrentInterface.LayoutMutex){
- IsQueueForRedraw = false;
- if (Parent == null)
- return;
+ parentRWLock.EnterReadLock ();
+ if (parent != null) {
Parent.RegisterClip (LastPaintedSlot);
Parent.RegisterClip (Slot);
}
+ parentRWLock.ExitReadLock ();
}
/// <summary>
/// Add clip rectangle to this.clipping and propagate up to root
diff --git a/src/GraphicObjects/Group.cs b/src/GraphicObjects/Group.cs
index 1b5847d4..e7604842 100644
--- a/src/GraphicObjects/Group.cs
+++ b/src/GraphicObjects/Group.cs
@@ -31,12 +31,15 @@ using System.Xml.Serialization;
using Cairo;
using System.Diagnostics;
using System.Reflection;
+using System.Threading;
namespace Crow
{
public class Group : GraphicObject
{
+ protected ReaderWriterLockSlim childrenRWLock = new ReaderWriterLockSlim();
+
#region CTOR
public Group () : base() {}
public Group(Interface iface) : base(iface){}
@@ -62,10 +65,13 @@ namespace Crow
set { _multiSelect = value; }
}
public virtual void AddChild(GraphicObject g){
- lock (Children) {
- g.Parent = this;
- Children.Add (g);
- }
+ childrenRWLock.EnterWriteLock();
+
+ g.Parent = this;
+ Children.Add (g);
+
+ childrenRWLock.ExitWriteLock();
+
g.RegisteredLayoutings = LayoutingType.None;
g.LayoutChanged += OnChildLayoutChanges;
g.RegisterForLayouting (LayoutingType.Sizing | LayoutingType.ArrangeChildren);
@@ -79,8 +85,11 @@ namespace Crow
CurrentInterface.HoverWidget = null;
}
- lock (Children)
- Children.Remove(child);
+ childrenRWLock.EnterWriteLock ();
+
+ Children.Remove(child);
+
+ childrenRWLock.ExitWriteLock ();
if (child == largestChild && Width == Measure.Fit)
searchLargestChild ();
@@ -96,10 +105,13 @@ namespace Crow
child.Dispose ();
}
public virtual void InsertChild (int idx, GraphicObject g) {
- lock (Children) {
- g.Parent = this;
- Children.Insert (idx, g);
- }
+ childrenRWLock.EnterWriteLock ();
+
+ g.Parent = this;
+ Children.Insert (idx, g);
+
+ childrenRWLock.ExitWriteLock ();
+
g.RegisteredLayoutings = LayoutingType.None;
g.LayoutChanged += OnChildLayoutChanges;
g.RegisterForLayouting (LayoutingType.Sizing | LayoutingType.ArrangeChildren);
@@ -109,15 +121,17 @@ namespace Crow
}
public virtual void ClearChildren()
{
- lock (Children) {
- while (Children.Count > 0) {
- GraphicObject g = Children [Children.Count - 1];
- g.LayoutChanged -= OnChildLayoutChanges;
- Children.RemoveAt (Children.Count - 1);
- g.Dispose ();
- }
+ childrenRWLock.EnterWriteLock ();
+
+ while (Children.Count > 0) {
+ GraphicObject g = Children [Children.Count - 1];
+ g.LayoutChanged -= OnChildLayoutChanges;
+ Children.RemoveAt (Children.Count - 1);
+ g.Dispose ();
}
+ childrenRWLock.ExitWriteLock ();
+
resetChildrenMaxSize ();
this.RegisterForLayouting (LayoutingType.Sizing);
@@ -128,20 +142,24 @@ namespace Crow
{
if (Children.Contains(w))
{
- lock (Children) {
- Children.Remove (w);
- Children.Add (w);
- }
+ childrenRWLock.EnterWriteLock ();
+
+ Children.Remove (w);
+ Children.Add (w);
+
+ childrenRWLock.ExitWriteLock ();
}
}
public void putWidgetOnBottom(GraphicObject w)
{
if (Children.Contains(w))
{
- lock (Children) {
- Children.Remove (w);
- Children.Insert (0, w);
- }
+ childrenRWLock.EnterWriteLock ();
+
+ Children.Remove (w);
+ Children.Insert (0, w);
+
+ childrenRWLock.ExitWriteLock ();
}
}
@@ -149,24 +167,31 @@ namespace Crow
public override void OnDataSourceChanged (object sender, DataSourceChangeEventArgs e)
{
base.OnDataSourceChanged (this, e);
- lock (Children) {
- foreach (GraphicObject g in children)
- if (g.localDataSourceIsNull & g.localLogicalParentIsNull)
- g.OnDataSourceChanged (g, e);
- }
+
+ childrenRWLock.EnterReadLock ();
+
+ foreach (GraphicObject g in children)
+ if (g.localDataSourceIsNull & g.localLogicalParentIsNull)
+ g.OnDataSourceChanged (g, e);
+
+ childrenRWLock.ExitReadLock ();
}
public override GraphicObject FindByName (string nameToFind)
{
if (Name == nameToFind)
return this;
GraphicObject tmp = null;
- lock (Children) {
- foreach (GraphicObject w in Children) {
- tmp = w.FindByName (nameToFind);
- if (tmp != null)
- break;
- }
+
+ childrenRWLock.EnterReadLock ();
+
+ foreach (GraphicObject w in Children) {
+ tmp = w.FindByName (nameToFind);
+ if (tmp != null)
+ break;
}
+
+ childrenRWLock.ExitReadLock ();
+
return tmp;
}
public override bool Contains (GraphicObject goToFind)
@@ -207,10 +232,11 @@ namespace Crow
{
base.OnLayoutChanges (layoutType);
+ childrenRWLock.EnterReadLock ();
//position smaller objects in group when group size is fit
switch (layoutType) {
case LayoutingType.Width:
- foreach (GraphicObject c in Children){
+ foreach (GraphicObject c in Children) {
if (c.Width.Units == Unit.Percent)
c.RegisterForLayouting (LayoutingType.Width);
else
@@ -226,6 +252,7 @@ namespace Crow
}
break;
}
+ childrenRWLock.ExitReadLock ();
}
protected override void onDraw (Context gr)
{
@@ -239,11 +266,13 @@ namespace Crow
gr.Clip ();
}
- lock (Children) {
+ childrenRWLock.EnterReadLock ();
+
foreach (GraphicObject g in Children) {
g.Paint (ref gr);
}
- }
+
+ childrenRWLock.ExitReadLock ();
gr.Restore ();
}
protected override void UpdateCache (Context ctx)
@@ -268,16 +297,18 @@ namespace Crow
gr.Clip ();
}
- lock (Children) {
- foreach (GraphicObject c in Children) {
- if (!c.Visible)
- continue;
- if (Clipping.Contains (c.Slot + ClientRectangle.Position) == RegionOverlap.Out)
- continue;
- c.Paint (ref gr);
- }
+ childrenRWLock.EnterReadLock ();
+
+ foreach (GraphicObject c in Children) {
+ if (!c.Visible)
+ continue;
+ if (Clipping.Contains (c.Slot + ClientRectangle.Position) == RegionOverlap.Out)
+ continue;
+ c.Paint (ref gr);
}
+ childrenRWLock.ExitReadLock ();
+
#if DEBUG_CLIP_RECTANGLE
Clipping.stroke (gr, Color.Amaranth.AdjustAlpha (0.8));
#endif
diff --git a/src/GraphicObjects/TabView.cs b/src/GraphicObjects/TabView.cs
index c5292da7..abaa6ac0 100644
--- a/src/GraphicObjects/TabView.cs
+++ b/src/GraphicObjects/TabView.cs
@@ -176,17 +176,20 @@ namespace Crow
gr.Clip ();
}
- lock (Children) {
- TabItem[] tabItms = Children.Cast<TabItem> ().OrderBy (t => t.ViewIndex).ToArray ();
- for (int i = 0; i < tabItms.Length; i++) {
- if (tabItms [i] == Children [SelectedTab])
- continue;
- tabItms [i].Paint (ref gr);
- }
+ childrenRWLock.EnterReadLock ();
- if (SelectedTab < tabItms.Length && SelectedTab >= 0)
- Children [SelectedTab].Paint (ref gr);
+ TabItem[] tabItms = Children.Cast<TabItem> ().OrderBy (t => t.ViewIndex).ToArray ();
+ for (int i = 0; i < tabItms.Length; i++) {
+ if (tabItms [i] == Children [SelectedTab])
+ continue;
+ tabItms [i].Paint (ref gr);
}
+
+ if (SelectedTab < tabItms.Length && SelectedTab >= 0)
+ Children [SelectedTab].Paint (ref gr);
+
+ childrenRWLock.ExitReadLock ();
+
gr.Restore ();
}
diff --git a/src/GraphicObjects/Wrapper.cs b/src/GraphicObjects/Wrapper.cs
index e56d9332..4fff17ff 100644
--- a/src/GraphicObjects/Wrapper.cs
+++ b/src/GraphicObjects/Wrapper.cs
@@ -131,26 +131,32 @@ namespace Crow
else {
int dy = 0;
int largestChild = 0;
- lock (Children) {
- foreach (GraphicObject c in Children) {
- if (!c.Visible)
- continue;
- if (c.Height.Units == Unit.Percent &&
- c.RegisteredLayoutings.HasFlag (LayoutingType.Height))
- return -1;
- if (dy + c.Slot.Height > ClientRectangle.Height) {
- dy = 0;
- tmp += largestChild + Spacing;
- largestChild = c.Slot.Width;
- } else if (largestChild < c.Slot.Width)
- largestChild = c.Slot.Width;
- dy += c.Slot.Height + Spacing;
+ childrenRWLock.EnterReadLock();
+
+ foreach (GraphicObject c in Children) {
+ if (!c.Visible)
+ continue;
+ if (c.Height.Units == Unit.Percent &&
+ c.RegisteredLayoutings.HasFlag (LayoutingType.Height)) {
+ childrenRWLock.ExitReadLock();
+ return -1;
}
- if (dy == 0)
- tmp -= Spacing;
- return tmp + largestChild + 2 * Margin;
+ if (dy + c.Slot.Height > ClientRectangle.Height) {
+ dy = 0;
+ tmp += largestChild + Spacing;
+ largestChild = c.Slot.Width;
+ } else if (largestChild < c.Slot.Width)
+ largestChild = c.Slot.Width;
+
+ dy += c.Slot.Height + Spacing;
}
+
+ childrenRWLock.ExitReadLock ();
+
+ if (dy == 0)
+ tmp -= Spacing;
+ return tmp + largestChild + 2 * Margin;
}
} else if (Orientation == Orientation.Horizontal) {
Height = Measure.Stretched;
@@ -160,26 +166,32 @@ namespace Crow
else {
int dx = 0;
int tallestChild = 0;
- lock (Children) {
- foreach (GraphicObject c in Children) {
- if (!c.Visible)
- continue;
- if (c.Width.Units == Unit.Percent &&
- c.RegisteredLayoutings.HasFlag (LayoutingType.Width))
- return -1;
- if (dx + c.Slot.Width > ClientRectangle.Width) {
- dx = 0;
- tmp += tallestChild + Spacing;
- tallestChild = c.Slot.Height;
- } else if (tallestChild < c.Slot.Height)
- tallestChild = c.Slot.Height;
- dx += c.Slot.Width + Spacing;
+ childrenRWLock.EnterReadLock();
+
+ foreach (GraphicObject c in Children) {
+ if (!c.Visible)
+ continue;
+ if (c.Width.Units == Unit.Percent &&
+ c.RegisteredLayoutings.HasFlag (LayoutingType.Width)) {
+ childrenRWLock.ExitReadLock();
+ return -1;
}
- if (dx == 0)
- tmp -= Spacing;
- return tmp + tallestChild + 2 * Margin;
+ if (dx + c.Slot.Width > ClientRectangle.Width) {
+ dx = 0;
+ tmp += tallestChild + Spacing;
+ tallestChild = c.Slot.Height;
+ } else if (tallestChild < c.Slot.Height)
+ tallestChild = c.Slot.Height;
+
+ dx += c.Slot.Width + Spacing;
}
+
+ childrenRWLock.ExitReadLock();
+
+ if (dx == 0)
+ tmp -= Spacing;
+ return tmp + tallestChild + 2 * Margin;
}
}