A second option for LoaderQueue.
I've left the previous interface untouched, but changed a little the
implementation. Now touch() doesn't add directly the image pointer to the
queue, but it adds it to an input bucket (implemented as a plain queue)
without any checking and returns inmediately. 
Then on the 'threaded' method LoadNext we empty the input bucket into the
queue, with all uniqueness and reprioritization checking.
This implementation avoids completely having to lock the data, and so any
posibility of losing time on the main thread.
The startup time should be shorter also.

I have to solve at least one problem: the graphics insets have startLoading
called in document order, from first to last. Then they are added to the
queue in inversed order, and start loading from last to first. Maybe we
have to bypass this reprioritizing mechanism on startup somehow? Any clue
on how to solve this please?

(there are other remaining things if ever this gets incorporated: like to
where the LoaderQueue class belongs (BufferView?). Does it deserves its own
file, and so)

Regards, Alfredo

PS: As before, please correct without mercy but being nice...
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/20 12:27:32
@@ -28,9 +28,112 @@
 #include <boost/signals/trackable.hpp>
 
 #include <list>
+#include <set>
+#include <queue>
+#include <algorithm>
 
 namespace grfx {
 
+class LoaderQueue {
+public:
+	LoaderQueue();
+	void touch(Cache::ItemPtr item);
+	bool running();
+private:
+	std::list<Cache::ItemPtr> cache_queue_;
+	std::set<Cache::ItemPtr> cache_set_;
+	std::queue<Cache::ItemPtr> bucket1_;
+	std::queue<Cache::ItemPtr> bucket2_;
+	Timeout timer;
+	bool running_;
+
+	void emptyBucket();
+	void addToQueue(Cache::ItemPtr item);
+	void loadNext();
+	void startLoader();
+	void stopLoader();
+};
+
+void LoaderQueue::loadNext() 
+{
+	emptyBucket();
+	cout << cache_queue_.size()
+	     << " items in the queue" << endl; 
+
+	if ( cache_queue_.size() ) {
+		cache_queue_.front()->startLoading();
+		cache_set_.erase(cache_queue_.front());
+		cache_queue_.pop_front();
+	}
+	if (cache_queue_.size() || bucket1_.size()) {
+		startLoader();
+	} else {
+		stopLoader();
+	}
+}
+
+LoaderQueue::LoaderQueue() : timer( 100 , Timeout::ONETIME ), 
+			     running_( false )
+{
+	timer.timeout.connect( boost::bind( &LoaderQueue::loadNext, this));
+}
+
+void LoaderQueue::emptyBucket()
+{
+	cout << "emptying bucket" << endl;
+	swap(bucket1_, bucket2_);
+	while (! bucket2_.empty()) {
+		addToQueue(bucket2_.front());
+		bucket2_.pop();
+	}
+}
+
+void LoaderQueue::startLoader()
+{
+	cout << "waking up" << endl;
+	running_ = true ;
+	timer.start();
+}
+
+void LoaderQueue::stopLoader()
+{
+	timer.stop();
+	running_ = false ;
+	cout << "going to sleep" << endl;
+}
+
+bool LoaderQueue::running()
+{
+	return running_ ;
+}
+
+void LoaderQueue::touch(Cache::ItemPtr item)
+{
+	if ( ! running_ )
+		startLoader();
+	bucket1_.push(item);
+}
+
+
+void LoaderQueue::addToQueue(Cache::ItemPtr item)
+{
+	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 );
+		if (it == end) {
+			cout << "key not found!" << endl;
+		} else
+			cache_queue_.erase( it );
+	} 
+	cache_queue_.push_front( item );
+}
+
+LoaderQueue LQ;
+
 struct Loader::Impl : boost::signals::trackable {
 	///
 	Impl(Params const &);
@@ -66,8 +169,6 @@
 	///
 	Params params_;
 
-	///
-	Timeout timer;
 	// Multiple Insets can share the same image
 	typedef std::list<Inset const *> InsetList;
 	///
@@ -196,10 +297,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));
 }
 
 
@@ -293,7 +392,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 +401,7 @@
 	if (it == end)
 		insets.push_back(&inset);
 	view = bv.owner()->view();
-
-	timer.start();
+	LQ.touch(cached_item_);
 }
 
 

Reply via email to