I'm fiddling a little with the graphics loader, and I started to implement a
pseudo threaded version of it (patch attached).

It works as follows: there is this LoaderQueue class (I think every
BufferView should have one, right now is simply a global class), which
implements a queue with a twist:

1) Elements are unique
2) Reinserting an element reprioritizes it to the top

I.e. it sort of works like the 'touch' command.

Right now it's implemented as a queue + a set, so it's O(ln n) for the
'first time insert' case, and O(n) for the 'already have it' case.
I plan to make it O(ln n) always.

His loadNext method should run in an independent thread, right now it runs
with a timer that comes back every .1 seconds. I've put a minimal locking
mecanism. Should be trivial to convert to a real thread once boost.threads
is installed on the LyX tree.

This LoaderQueue is called from Loader::startLoading, i.e. from there we
'touch' the graphic. Nothing is really loaded on screen yet. The real
loading is done on the loadNext method (the 'threaded' one).

It works pretty nicely I think (except for the O(n) thingie and some other
details). And the patch is very minimal.

I know that the coding style is broken, please correct me without mercy.
Anyway of course it's not to be applied, It's only a proof of concept.

I have some questions about when these Loadings are called, so if someone
thinks that this is not a complete trash then I go on and ask them.

Please be nice.

Regards, Alfredo
? patch.diff
Index: GraphicsLoader.C
===================================================================
RCS file: /cvs/lyx/lyx-devel/src/graphics/GraphicsLoader.C,v
retrieving revision 1.12
diff -u -r1.12 GraphicsLoader.C
--- GraphicsLoader.C	2003/02/13 16:53:00	1.12
+++ GraphicsLoader.C	2003/02/19 08:11:58
@@ -28,9 +28,60 @@
 #include <boost/signals/trackable.hpp>
 
 #include <list>
+#include <set>
 
 namespace grfx {
 
+class LoaderQueue {
+public:
+	LoaderQueue():timer( 100 , Timeout::ONETIME )
+	{
+		timer.timeout.connect( boost::bind( &LoaderQueue::loadNext, this));
+		locked = false;
+		timer.start();
+	}
+	void touch(Cache::ItemPtr item) {
+
+		if(locked)
+			return;
+
+		locked = true;
+
+		if( !cache_set_.insert(item).second ) {
+
+			list<Cache::ItemPtr>::iterator 
+				it = cache_queue_.begin();
+			list<Cache::ItemPtr>::iterator 
+				end = cache_queue_.end();
+
+			it = std::find( it, end, item );
+			cache_queue_.erase( it );
+		} 
+		cache_queue_.push_front( item );
+		locked = false;
+	}
+private:
+	bool locked;
+	std::list<Cache::ItemPtr> cache_queue_;
+	std::set<Cache::ItemPtr> cache_set_;
+	Timeout timer;
+	void loadNext() {
+		if(locked)
+			return;
+		locked = true;
+		int counter = 10;
+		while (cache_queue_.size() && --counter) {
+			cout << cache_queue_.size()
+			     << " items in the queue" << endl; 
+			cache_queue_.front()->startLoading();
+			cache_set_.erase(cache_queue_.front());
+			cache_queue_.pop_front();
+		}
+		locked = false;
+		timer.start();
+	};
+} LQ;
+
 struct Loader::Impl : boost::signals::trackable {
 	///
 	Impl(Params const &);
@@ -66,8 +117,6 @@
 	///
 	Params params_;
 
-	///
-	Timeout timer;
 	// Multiple Insets can share the same image
 	typedef std::list<Inset const *> InsetList;
 	///
@@ -196,10 +245,8 @@
 
 
 Loader::Impl::Impl(Params const & params)
-	: status_(WaitingToLoad), params_(params),
-	  timer(2000, Timeout::ONETIME)
+	: status_(WaitingToLoad), params_(params)
 {
-	timer.timeout.connect(boost::bind(&Impl::checkedLoading, this));
 }
 
 
@@ -266,7 +313,6 @@
 	signal_();
 }
 
-
 void Loader::Impl::createPixmap()
 {
 	if (!cached_item_.get() ||
@@ -293,7 +339,7 @@
 
 void Loader::Impl::startLoading(Inset const & inset, BufferView const & bv)
 {
-	if (status_ != WaitingToLoad || timer.running())
+	if (status_ != WaitingToLoad)
 		return;
 
 	InsetList::const_iterator it  = insets.begin();
@@ -302,8 +348,7 @@
 	if (it == end)
 		insets.push_back(&inset);
 	view = bv.owner()->view();
-
-	timer.start();
+	LQ.touch(cached_item_);
 }
 
 
Index: GraphicsSupport.C
===================================================================
RCS file: /cvs/lyx/lyx-devel/src/graphics/GraphicsSupport.C,v
retrieving revision 1.7
diff -u -r1.7 GraphicsSupport.C
--- GraphicsSupport.C	2003/02/13 16:53:00	1.7
+++ GraphicsSupport.C	2003/02/19 08:11:58
@@ -33,7 +33,7 @@
 	VPList vps;
 	Row const * last_row = 0;
 
-	for (int height = 0; row && height < bv_height; row = row->next()) {
+	for (int height = 0; row && height < 2 *bv_height; row = row->next()) {
 		height += row->height();
 
 		if (vps.empty() || vps.back().par != row->par()) {
Index: PreviewImage.C
===================================================================
RCS file: /cvs/lyx/lyx-devel/src/graphics/PreviewImage.C,v
retrieving revision 1.11
diff -u -r1.11 PreviewImage.C
--- PreviewImage.C	2003/02/13 16:53:00	1.11
+++ PreviewImage.C	2003/02/19 08:11:58
@@ -33,7 +33,6 @@
 	Image const * image(Inset const &, BufferView const &);
 	///
 	void statusChanged();
-
 	///
 	PreviewImage const & parent_;
 	///

Reply via email to