+/////////////////////////////////////////////////////////////////////
+//
+// LoaderQueue
+//
+/////////////////////////////////////////////////////////////////////
+
+class LoaderQueue {
+public:
+ /// Use this to request that the item is loaded.
+ void touch(Cache::ItemPtr const & item);
+ /// Query whether the clock is ticking.
+ bool running() const;
+ ///get the and only instance of the class
+ static LoaderQueue & get();
+private:
+ /// This class is a singleton class... use LoaderQueue::get() instead
+ LoaderQueue();
+ /// The in-progress loading queue (elements are unique here).
+ list<Cache::ItemPtr> cache_queue_;
+ /// Used to make the insertion of new elements faster.
+ set<Cache::ItemPtr> cache_set_;
+ /// Newly touched elements go here. loadNext moves them to cache_queue_
+ queue<Cache::ItemPtr> bucket_;
+ ///
+ Timeout timer;
+ ///
+ bool running_;
+
+ /** This is the 'threaded' method, that does the loading in the
+ * background.
+ */
+ void loadNext();
+ ///
+ void startLoader();
+ ///
+ void stopLoader();
+};
+
+
+//static int s_numimages_ = 5;
+//static int s_millisecs_ = 500;
+
+static int s_numimages_ = 10;
+static int s_millisecs_ = 500;
+
+LoaderQueue & LoaderQueue::get()
+{
+ static LoaderQueue singleton;
+ return singleton;
+}
+
+
+void LoaderQueue::loadNext()
+{
+ LYXERR(Debug::GRAPHICS, "LoaderQueue: "
+ << cache_queue_.size() << " items in the queue");
+ int counter = s_numimages_;
+ while (!cache_queue_.empty() && counter--) {
+ Cache::ItemPtr ptr = cache_queue_.front();
+ cache_set_.erase(ptr);
+ cache_queue_.pop_front();
+ if (ptr->status() == WaitingToLoad)
+ ptr->startLoading();
+ }
+ if (!cache_queue_.empty())
+ startLoader();
+ else
+ stopLoader();
+}
+
+
+LoaderQueue::LoaderQueue() : timer(s_millisecs_, Timeout::ONETIME),
+ running_(false)
+{
+ timer.timeout.connect(bind(&LoaderQueue::loadNext, this));
+}
+
+
+void LoaderQueue::startLoader()
+{
+ LYXERR(Debug::GRAPHICS, "LoaderQueue: waking up");
+ running_ = true ;
+ timer.setTimeout(s_millisecs_);
+ timer.start();
+}
+
+
+void LoaderQueue::stopLoader()
+{
+ timer.stop();
+ running_ = false ;
+ LYXERR(Debug::GRAPHICS, "LoaderQueue: I'm going to sleep");
+}
+
+
+bool LoaderQueue::running() const
+{
+ return running_ ;
+}
+
+
+void LoaderQueue::touch(Cache::ItemPtr const & item)
+{
+ if (! cache_set_.insert(item).second) {
+ list<Cache::ItemPtr>::iterator
+ it = cache_queue_.begin();
+ list<Cache::ItemPtr>::iterator
+ end = cache_queue_.end();
+
+ it = find(it, end, item);
+ if (it != end)
+ cache_queue_.erase(it);
+ }
+ cache_queue_.push_front(item);
+ if (!running_)
+ startLoader();
+}
+
+
+
+/////////////////////////////////////////////////////////////////////
+//
+// GraphicsLoader
+//
+/////////////////////////////////////////////////////////////////////
+
+typedef shared_ptr<Image> ImagePtr;