[blam] Let the runtime take care of threading



commit bb23737b5e3c70cd9af5ab48fd02a114eedf3874
Author: Carlos MartÃn Nieto <carlos cmartin tk>
Date:   Sat Aug 4 20:55:12 2012 +0200

    Let the runtime take care of threading
    
    Use the task capabilities that the runtime gives
    us instead of reinenting them poorly

 src/Application.cs       |    7 +-
 src/Channel.cs           |   19 ++++++-
 src/ChannelCollection.cs |  146 ++++++++++++----------------------------------
 src/ChannelGroup.cs      |   19 ++++++
 4 files changed, 78 insertions(+), 113 deletions(-)
---
diff --git a/src/Application.cs b/src/Application.cs
index e7bbf46..942a7b1 100644
--- a/src/Application.cs
+++ b/src/Application.cs
@@ -170,7 +170,7 @@ namespace Imendio.Blam {
                 ShowNextUpdateTime();
             } else {
                 if(Conf.Get(Preference.REFRESH_AT_START, false) == true){
-                    mCollection.RefreshAll();
+                    mCollection.RefreshAllAsync();
                 }
             }
 
@@ -539,7 +539,6 @@ namespace Imendio.Blam {
             mainWindow.Hide();
             mCollection.SaveToFile ();
             ItemStore.Save();
-            mCollection.StopAllThreads();
 
             Gtk.Main.Quit();
         }
@@ -626,7 +625,7 @@ namespace Imendio.Blam {
         public void RefreshChannelActivated(IChannel channel)
         {
             if (channel != null) {
-                mCollection.Refresh (channel);
+                channel.RefreshAsync(null);
             }
         }
 
@@ -735,7 +734,7 @@ namespace Imendio.Blam {
         private bool TimeoutRefreshAll ()
         {
             ShowNextUpdateTime();
-            mCollection.RefreshAll();
+            mCollection.RefreshAllAsync();
 
             /* Continue until source is removed */
             return true;
diff --git a/src/Channel.cs b/src/Channel.cs
index 0508c90..ce2cbf0 100644
--- a/src/Channel.cs
+++ b/src/Channel.cs
@@ -25,6 +25,8 @@ namespace Imendio.Blam {
         void Setup();
         event ChannelEventHandler Updated;
         void RemoveItems();
+		bool Refresh();
+		void RefreshAsync(Action<bool> cb);
     }
 
     public class Channel : IChannel {
@@ -302,7 +304,22 @@ namespace Imendio.Blam {
 
 			return false;
 		}
-	}
 
+		delegate bool RefreshDelegate();
+		public bool Refresh()
+		{
+			return FeedUpdater.Update(this);
+		}
 
+		public void RefreshAsync(Action<bool> cb)
+		{
+			var fun = new RefreshDelegate(Refresh);
+			fun.BeginInvoke(ar => {
+				bool res = fun.EndInvoke(ar);
+				if (cb != null)
+					cb(res);
+			},
+			null);
+		}
+	}
 }
diff --git a/src/ChannelCollection.cs b/src/ChannelCollection.cs
index 23aaffc..7f7a427 100644
--- a/src/ChannelCollection.cs
+++ b/src/ChannelCollection.cs
@@ -7,9 +7,11 @@
 
 using System;
 using System.Collections;
+using System.Linq;
 using System.IO;
 using System.Reflection;
 using System.Threading;
+using System.Threading.Tasks;
 using System.Xml;
 using System.Xml.Serialization;
 
@@ -27,8 +29,6 @@ namespace Imendio.Blam {
 
 	public string FileName;
 
-	private Queue mQueue;
-	private IList mRunningList;
 	private Object clock = new Object();
 
 	private bool mDirty = false;
@@ -84,8 +84,6 @@ namespace Imendio.Blam {
 
 	public ChannelCollection ()
 	{
-	    mQueue = Queue.Synchronized (new Queue ());
-	    mRunningList = ArrayList.Synchronized (new ArrayList ());
 	}
 
 	public static ChannelCollection LoadFromFile (string file)
@@ -173,8 +171,8 @@ namespace Imendio.Blam {
 	    }
 	}
 
-	public void Add (IChannel channel)
-	{
+        public void Add (IChannel channel)
+        {
 	    // Not the most efficient way of doing things :)
 	    foreach (Channel ch in mChannels) {
 		if (channel.Url == ch.Url) {
@@ -187,27 +185,26 @@ namespace Imendio.Blam {
         }
 
         mChannels.Add (channel);
-        Refresh (channel);
-
-	    if (ChannelAdded != null) {
-		ChannelAdded (channel);
-	    }
-
-        MarkAsDirty(true);
+            channel.RefreshAsync(updated => {
+                MarkAsDirty(true);
+                if (ChannelAdded != null)
+                    ChannelAdded (channel);
+            });
 	}
 
-	public void Add(ChannelGroup group, IChannel channel)
-	{
-		group.Add(channel);
-		Refresh(channel);
+        public void Add(ChannelGroup group, IChannel channel)
+        {
+            group.Add(channel);
+            channel.RefreshAsync(updated => {
+                channel.Updated += Updated;
 
-            channel.Updated += Updated;
-		if(ChannelGroupAdded != null){
-			ChannelGroupAdded(group, channel);
-		}
+                if(ChannelGroupAdded != null){
+                    ChannelGroupAdded(group, channel);
+                }
 
-		MarkAsDirty(true);
-	}
+                MarkAsDirty(true);
+            });
+        }
 
 	public void Updated (IChannel channel)
 	{
@@ -242,96 +239,29 @@ namespace Imendio.Blam {
         MarkAsDirty(true);
 	}
 
-	public void Refresh (IChannel channel)
-	{
-	    mQueue.Enqueue (channel);
-	    EmitChannelRefreshStarted (channel);
-
-	    Thread thread = new Thread (new ThreadStart (UpdateThread));
-	    mRunningList.Add (thread);
+        delegate void RefreshAllDelegate();
 
-	    thread.Start ();
-	}
-
-	private void QueueChannelRefresh (IChannel channel)
-	{
-	    mQueue.Enqueue (channel);
-	    EmitChannelRefreshStarted (channel);
-	}
-
-	private void StartRefreshThreads (int maxNrOfThreads)
-	{
-	    // Only start a maximum of five threads
-	    for (int i = 0; i < 5 && i < maxNrOfThreads; ++i) { 
-		Thread thread = new Thread (new ThreadStart (UpdateThread));
-		mRunningList.Add (thread);
-		thread.Start ();
-	    }
-	}
-
-    public void StopAllThreads()
-    {
-        foreach(Thread t in mRunningList){
-            t.Abort();
+        public void RefreshAllAsync()
+        {
+            var fun = new RefreshAllDelegate(RefreshAll);
+            fun.BeginInvoke(fun.EndInvoke, null);
         }
 
-        mRunningList.Clear();
-        mQueue.Clear();
-    }
-
-	public void RefreshAll ()
-	{
-	    int nrOfChannels = 0;
-	    
-	    foreach (Channel channel in mChannels) {
-		QueueChannelRefresh (channel);
-		nrOfChannels++;
-	    }
-
-        foreach(ChannelGroup group in Groups){
-            foreach(Channel channel in group.Channels){
-                QueueChannelRefresh(channel);
-                nrOfChannels++;
-            }
-        }
-
-	    StartRefreshThreads (nrOfChannels);
-	}
-
-	private void UpdateThread ()
-	{
-	    while (true) {
-		try {
-		    IChannel tmp = (IChannel) mQueue.Dequeue ();
-            Channel channel;
-
-           if(tmp is ChannelGroup){
-               mRunningList.Remove(Thread.CurrentThread);
-               return;
+        public void RefreshAll ()
+        {
+            var all = mChannels.Cast<Channel>();
+            foreach(ChannelGroup group in Groups){
+                all.Union(group.Channels.Cast<Channel>());
             }
 
-            channel = tmp as Channel;
-            bool updated = FeedUpdater.Update (channel);
-
-		    if (updated) {
-			MarkAsDirty (true);
-		    }	
-
-		    new MainloopEmitter (this.ChannelRefreshFinished, channel).Emit ();
-#if ENABLE_NOTIFY
-            /* Make sure we have something to say and the user isn't watching us */
-            if(mQueue.Count == 0 &&
-                    NrOfUnreadItems != 0 && Application.TheApp.Window.IsActive == false){
-                UnreadNotification.NotifyUnreadPosts(NrOfUnreadItems, NrOfNewItems);
-            }
-#endif
-		} catch (InvalidOperationException) {
-		    break;
-		}
-	    }
-
-	    mRunningList.Remove (Thread.CurrentThread);
-	}
+            Parallel.ForEach(mChannels.Cast<Channel>(), c => {
+                bool updated = c.Refresh();
+                if (updated) {
+                    MarkAsDirty (true);
+                }
+                new MainloopEmitter (this.ChannelRefreshFinished, c).Emit ();
+            });
+        }
 
 	private void EmitChannelRefreshStarted (IChannel channel)
 	{
diff --git a/src/ChannelGroup.cs b/src/ChannelGroup.cs
index 5ff0c20..4c1df3d 100644
--- a/src/ChannelGroup.cs
+++ b/src/ChannelGroup.cs
@@ -7,6 +7,8 @@
 using System;
 using System.Collections;
 using System.Xml.Serialization;
+using System.Threading.Tasks;
+using System.Linq;
 
 namespace Imendio.Blam
 {
@@ -157,5 +159,22 @@ namespace Imendio.Blam
             }
             return null;
         }
+
+		public delegate bool RefreshDelegate();
+		public bool Refresh()
+		{
+			Parallel.ForEach(Channels.Cast<Channel>(), c => c.Refresh());
+			return true; // Whatever
+		}
+
+		public void RefreshAsync(Action<bool> cb)
+		{
+			var fun = new RefreshDelegate(Refresh);
+			fun.BeginInvoke(ar => {
+				bool res = fun.EndInvoke(ar);
+				if (cb != null)
+					cb(res);
+			}, null);
+		}
     }
 }



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]