]> O.S.I.I.S - jp/crow.git/commitdiff
full IDisposable implementation (#34)
authorj-p <jp.bruyere@live.be>
Mon, 28 Aug 2017 03:12:19 +0000 (05:12 +0200)
committerGitHub <noreply@github.com>
Mon, 28 Aug 2017 03:12:19 +0000 (05:12 +0200)
* full implementation of IDisposable, not stable, lock and still leaking

* override dispose in popper to handle _content not yet in graphic tree (when never shown), test focusedWidget when disposing

* prevent canceling thread multiple times causing a deadlock

* test parent type when trying to close window

Tests/InterfaceControler.cs
Tests/Tests.csproj
src/CrowThread.cs
src/GraphicObjects/GraphicObject.cs
src/GraphicObjects/Group.cs
src/GraphicObjects/Popper.cs
src/GraphicObjects/PrivateContainer.cs
src/GraphicObjects/TemplatedGroup.cs
src/GraphicObjects/Window.cs
src/Interface.cs

index 4d988c10b63b51c88c25370b10bc1db0dac99177..4da65d1ee2e982f40b1ec9fb7d21a7bb0f126fe5 100644 (file)
@@ -162,7 +162,7 @@ namespace Crow
 
                        while (true) {
                                CrowInterface.Update ();
-                               //Thread.Sleep (1);
+                               Thread.Sleep (1);
                        }
                }
 
index 2adcdb16b88ff81baa386c3c2c99f0d7894d731f..21cb740d0eb55b1b966ec5d24dc7386f03ce2311 100644 (file)
@@ -8,7 +8,7 @@
     <OutputType>Exe</OutputType>
     <RootNamespace>Tests</RootNamespace>
     <AssemblyName>Tests</AssemblyName>
-    <StartupObject>Tests.Showcase</StartupObject>
+    <StartupObject>Tests.BasicTests</StartupObject>
     <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
     <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
     <ReleaseVersion>0.5</ReleaseVersion>
index fbcdc9569d96f2b7796b0a1d250852cba2f60c6e..823fe1a63b0df92776267b413410c42900294144 100644 (file)
@@ -33,7 +33,7 @@ namespace Crow
        /// Thread monitored by current interface with Finished event when state==Stopped
        /// </summary>
        public class CrowThread {
-               public bool cancel = false;
+               public bool cancelRequested = false;
                Thread thread;
                public event EventHandler Finished;
                public GraphicObject Host;
@@ -53,11 +53,9 @@ namespace Crow
                }
                public void Start() { thread.Start();}
                public void Cancel(){
-                       if (thread.IsAlive){
-                               cancel = true;
-                               //cancelLoading = true;
+                       if (thread.IsAlive & !cancelRequested){
+                               cancelRequested = true;
                                thread.Join ();
-                               //cancelLoading = false;
                        }
                        lock (Host.currentInterface.CrowThreads)
                                Host.currentInterface.CrowThreads.Remove (this);
index 8fd9a6e99a1945c576b01a27295e5481d373509c..93e812def3461c4e9681b59d9c4028ed6e507aae 100644 (file)
@@ -41,22 +41,51 @@ namespace Crow
        public class GraphicObject : ILayoutable, IValueChange, IDisposable
        {
                #region IDisposable implementation
+               protected bool disposed = false;
+
+               public void Dispose(){  
+                       Dispose(true);  
+                       GC.SuppressFinalize(this);  
+               }  
+               ~GraphicObject(){
+                       Dispose(false);
+               }
+               protected virtual void Dispose(bool disposing){
+                       if (disposed){
+                               #if DEBUG_DISPOSE
+                               Debug.WriteLine ("Trying to dispose already disposed obj: {0}", this.ToString());
+                               #endif
+                               return;
+                       }
 
-               public virtual void Dispose ()
-               {
-                       #if DEBUG_DISPOSE
-                       Debug.WriteLine ("{0} Disposed", this.ToString());
-                       #endif
-
-                       parent = null;
-                       if (IsQueueForRedraw)
-                               Debugger.Break ();
-                       if (!localDataSourceIsNull)
-                               DataSource = null;
+                       if (disposing) {
+                               #if DEBUG_DISPOSE
+                               Debug.WriteLine ("Disposing: {0}", this.ToString());
+                               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;
+                               }
+                               if (currentInterface.ActiveWidget != null) {
+                                       if (currentInterface.ActiveWidget.IsOrIsInside (this))
+                                               currentInterface.ActiveWidget = null;
+                               }
+                               if (currentInterface.FocusedWidget != null) {
+                                       if (currentInterface.FocusedWidget.IsOrIsInside (this))
+                                               currentInterface.FocusedWidget = null;
+                               }
+                               if (!localDataSourceIsNull)
+                                       DataSource = null;
+                               parent = null;
+                       } else
+                               Debug.WriteLine ("!!! Finalized by GC: {0}", this.ToString ());
                        Clipping?.Dispose ();
                        bmp?.Dispose ();
-               }
+                       disposed = true;
 
+               }  
                #endregion
 
                internal static ulong currentUid = 0;
@@ -826,7 +855,9 @@ namespace Crow
                /// <summary>
                /// return true if this is contained inside go
                /// </summary>
-               public bool IsInside(GraphicObject go){
+               public bool IsOrIsInside(GraphicObject go){
+                       if (this == go)
+                               return true;
                        ILayoutable p = this.Parent;
                        while (p != null) {
                                if (p == go)
index f3026290e6de145b8c7430fe1cc9b92f2fae1e53..e7d7d4d4a163d10fbff249903d60624bd228d095 100644 (file)
@@ -73,13 +73,9 @@ namespace Crow
         public virtual void RemoveChild(GraphicObject child)        
                {
                        child.LayoutChanged -= OnChildLayoutChanges;
-                       child.Parent = null;
 
                        //check if HoverWidget is removed from Tree
-                       if (currentInterface.HoverWidget != null) {
-                               if (currentInterface.HoverWidget.IsInside(this))
-                                       currentInterface.HoverWidget = null;
-                       }
+
 
                        lock (children)
                Children.Remove(child);
@@ -366,11 +362,13 @@ namespace Crow
                }
                #endregion
 
-               public override void Dispose ()
+               protected override void Dispose (bool disposing)
                {
-                       foreach (GraphicObject c in children)
-                               c.Dispose ();
-                       base.Dispose ();
+                       if (disposing) {
+                               foreach (GraphicObject c in children)
+                                       c.Dispose ();
+                       }
+                       base.Dispose (disposing);
                }
        }
 }
index 3ba6d71195f1f5b34b48721fdec618f1a6415a06..d6e363469fa5b0390ebbc94feb7b3e448984e39c 100644 (file)
@@ -240,5 +240,14 @@ namespace Crow
                        }
                        Unpoped.Raise (this, e);
                }
+
+               protected override void Dispose (bool disposing)
+               {
+                       if (_content != null && disposing) {
+                               if (_content.Parent == null)
+                                       _content.Dispose ();
+                       }
+                       base.Dispose (disposing);
+               }
        }
 }
index 89b3075312a86aaa977859402e386bc42c593a10..077f732f3d382013a77a43f4f49671c97cf9ddb0 100644 (file)
@@ -54,14 +54,9 @@ namespace Crow
 
                        if (child != null) {
                                //check if HoverWidget is removed from Tree
-                               if (currentInterface.HoverWidget != null) {
-                                       if (currentInterface.HoverWidget.IsInside(this))
-                                               currentInterface.HoverWidget = null;
-                               }
                                contentSize = new Size (0, 0);
                                child.LayoutChanged -= OnChildLayoutChanges;
                                child.Dispose ();
-                               child.Parent = null;
                                this.RegisterForGraphicUpdate ();
                        }
 
@@ -213,11 +208,11 @@ namespace Crow
                }
                #endregion
 
-               public override void Dispose ()
+               protected override void Dispose (bool disposing)
                {
-                       if (child != null)
+                       if (disposing && child != null)
                                child.Dispose ();
-                       base.Dispose ();
+                       base.Dispose (disposing);
                }
        }
 }
index e4e294043ab8972fb002c35dc0f8bff68dc70a4c..1cbc4935366c905cbdd6aa0f916129f7001e048c 100644 (file)
@@ -273,8 +273,10 @@ namespace Crow
                                ItemTemplates ["default"] = Interface.GetItemTemplate (ItemTemplate);
 
                        for (int i = 1; i <= (data.Count / itemPerPage) + 1; i++) {
-                               if ((bool)loadingThread?.cancel)
+                               if ((bool)loadingThread?.cancelRequested) {
+                                       this.Dispose ();
                                        return;
+                               }
                                loadPage (i);
                                Thread.Sleep (1);
                        }
@@ -315,8 +317,10 @@ namespace Crow
                        for (int i = (pageNum - 1) * itemPerPage; i < pageNum * itemPerPage; i++) {
                                if (i >= data.Count)
                                        break;
-                               if ((bool)loadingThread?.cancel)
+                               if ((bool)loadingThread?.cancelRequested) {
+                                       page.Dispose ();
                                        return;
+                               }
 
                                loadItem (i, page);
                        }
@@ -336,7 +340,7 @@ namespace Crow
                string getItempKey(Type dataType, object o){
                        try {
                                return dataType.GetProperty (_dataTest).GetGetMethod ().Invoke (o, null).ToString();
-                       } catch (Exception ex) {
+                       } catch  {
                                return dataType.FullName;
                        }
                }
@@ -426,11 +430,11 @@ namespace Crow
                        SelectedIndex = data.IndexOf((sender as GraphicObject).DataSource);
                }
 
-               public override void Dispose ()
+               protected override void Dispose (bool disposing)
                {
-                       if (loadingThread != null)
+                       if (disposing && loadingThread != null)
                                loadingThread.Cancel ();
-                       base.Dispose ();
+                       base.Dispose (disposing);
                }
        }
 }
index e0c97ea99b7b8b0dc0d83038f38c3e58913be6de..176e8d9099db0cafe633039b26cd51b555d484eb 100644 (file)
@@ -391,7 +391,12 @@ namespace Crow
 
                protected void close(){
                        Closing.Raise (this, null);
-                       currentInterface.DeleteWidget (this);
+                       if (Parent is Interface)
+                               (Parent as Interface).DeleteWidget (this);
+                       else if (Parent is Group)
+                               (Parent as Group).RemoveChild (this);
+                       else if (Parent is PrivateContainer)
+                               (Parent as Container).Child = null;
                }
        }
 }
index baa466679281028ac97b114c71035303180d6675..24bd3ca23adaa84078ea82c1c1c3ebef0950207b 100644 (file)
@@ -592,10 +592,6 @@ namespace Crow
                /// <summary>Set visible state of widget to false and remove if from the graphic tree</summary>
                public void DeleteWidget(GraphicObject g)
                {
-                       if (_hoverWidget != null) {
-                               if (_hoverWidget.IsInside(g))
-                                       HoverWidget = null;
-                       }
                        lock (UpdateMutex) {
                                RegisterClip (g.ScreenCoordinates (g.LastPaintedSlot));
                                GraphicTree.Remove (g);
@@ -611,10 +607,6 @@ namespace Crow
                                        //TODO:parent is not reset to null because object will be added
                                        //to ObjectToRedraw list, and without parent, it fails
                                        GraphicObject g = GraphicTree [0];
-                                       if (_hoverWidget != null) {
-                                               if (_hoverWidget.IsInside(g))
-                                                       HoverWidget = null;
-                                       }
                                        RegisterClip (g.ScreenCoordinates (g.LastPaintedSlot));
                                        GraphicTree.RemoveAt (0);
                                        g.Dispose ();