From 546e14eb161291a7c9de6c954b38cf410982895d Mon Sep 17 00:00:00 2001 From: Angus Leeming Date: Fri, 21 Feb 2003 10:04:08 +0000 Subject: [PATCH] Alfredo's Loader Queue. git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@6221 a592a061-630c-0410-9148-cb99ea01b6c8 --- lib/CREDITS | 3 + lib/ChangeLog | 4 ++ src/graphics/ChangeLog | 8 +++ src/graphics/GraphicsLoader.C | 51 ++------------- src/graphics/GraphicsSupport.C | 100 ---------------------------- src/graphics/GraphicsSupport.h | 48 -------------- src/graphics/LoaderQueue.C | 116 +++++++++++++++++++++++++++++++++ src/graphics/LoaderQueue.h | 69 ++++++++++++++++++++ src/graphics/Makefile.am | 4 +- 9 files changed, 206 insertions(+), 197 deletions(-) delete mode 100644 src/graphics/GraphicsSupport.C delete mode 100644 src/graphics/GraphicsSupport.h create mode 100644 src/graphics/LoaderQueue.C create mode 100644 src/graphics/LoaderQueue.h diff --git a/lib/CREDITS b/lib/CREDITS index bddfd38cc9..a99980dc9d 100644 --- a/lib/CREDITS +++ b/lib/CREDITS @@ -34,6 +34,9 @@ and a few other (not so) minor things, like rewriting most of the LyX kernel. Also current source maintainer. +@bAlfredo Braunstein +@iE-mail: abraunst@libero.it + a (psuedo) threaded graphics loader queue @bChristian Buescher user-definable keys, lyxserver and more @bFrancesc Burrull i Mestres diff --git a/lib/ChangeLog b/lib/ChangeLog index 1a1c306891..c880a745d8 100644 --- a/lib/ChangeLog +++ b/lib/ChangeLog @@ -4,6 +4,10 @@ * examples/de_beispiel_roh.lyx: Small fixes to make it look like a German document +2003-02-21 Angus Leeming + + * CREDITS: Add Alfredo Braunstein. + 2003-02-21 Angus Leeming * ui/default.ui: change bibkey-insert to bibtem-insert. diff --git a/src/graphics/ChangeLog b/src/graphics/ChangeLog index 125a0ccfc4..788e5cf453 100644 --- a/src/graphics/ChangeLog +++ b/src/graphics/ChangeLog @@ -1,3 +1,11 @@ +2003-02-20 Alfredo Braunstein + + * LoaderQueue.[Ch]: added. Implements a service queue that loads + images in background + * GraphicsSupport.[Ch]: removed + * Makefile.am: the changes above + * GraphicsLoader.C: use the loading queue + 2003-01-21 Angus Leeming * PreviewLoader.C (dumpPreamble): ensure that \lyxlock does not prevent diff --git a/src/graphics/GraphicsLoader.C b/src/graphics/GraphicsLoader.C index b7c1d953a4..5bfa5ac6cc 100644 --- a/src/graphics/GraphicsLoader.C +++ b/src/graphics/GraphicsLoader.C @@ -18,7 +18,7 @@ #include "GraphicsCacheItem.h" #include "GraphicsImage.h" #include "GraphicsParams.h" -#include "GraphicsSupport.h" +#include "LoaderQueue.h" #include "frontends/LyXView.h" #include "frontends/Timeout.h" @@ -66,8 +66,6 @@ private: /// Params params_; - /// - Timeout timer; // Multiple Insets can share the same image typedef std::list InsetList; /// @@ -196,10 +194,8 @@ Image const * Loader::image() const 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 +289,7 @@ void Loader::Impl::createPixmap() 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(); @@ -303,46 +299,7 @@ void Loader::Impl::startLoading(Inset const & inset, BufferView const & bv) insets.push_back(&inset); view = bv.owner()->view(); - timer.start(); -} - - -namespace { - -struct FindVisibleInset { - - FindVisibleInset(std::list const & vps) : vps_(vps) {} - - bool operator()(Inset const * inset_ptr) - { - if (!inset_ptr) - return false; - return isInsetVisible(*inset_ptr, vps_); - } - -private: - std::list const & vps_; -}; - -} // namespace anon - - -void Loader::Impl::checkedLoading() -{ - if (insets.empty() || !view.get()) - return; - - std::list const vps = - getVisibleParagraphs(*view.get()); - - InsetList::const_iterator it = insets.begin(); - InsetList::const_iterator end = insets.end(); - - it = std::find_if(it, end, FindVisibleInset(vps)); - - // One of the insets is visible, so start loading the image. - if (it != end) - cached_item_->startLoading(); + LoaderQueue::get().touch(cached_item_); } diff --git a/src/graphics/GraphicsSupport.C b/src/graphics/GraphicsSupport.C deleted file mode 100644 index 1090df897c..0000000000 --- a/src/graphics/GraphicsSupport.C +++ /dev/null @@ -1,100 +0,0 @@ -/** - * \file GraphicsSupport.C - * This file is part of LyX, the document processor. - * Licence details can be found in the file COPYING. - * - * \author Angus Leeming - * - * Full author contact details are available in file CREDITS - */ - -#include - -#include "GraphicsSupport.h" - -#include "BufferView.h" -#include "lyxtext.h" -#include "lyxrow.h" -#include "paragraph.h" -#include "frontends/Painter.h" - - -typedef std::list VPList; - - -VPList const getVisibleParagraphs(BufferView const & bv) -{ - // top_y is not const because it's reset by getRowNearY. - int top_y = bv.text->first_y; - Row const * row = bv.text->getRowNearY(top_y); - - int const bv_height = bv.painter().paperHeight(); - - VPList vps; - Row const * last_row = 0; - - for (int height = 0; row && height < bv_height; row = row->next()) { - height += row->height(); - - if (vps.empty() || vps.back().par != row->par()) { - vps.push_back(VisibleParagraph(row->par(), - row->pos(), - row->par()->size())); - } - - last_row = row; - } - - // If the end of the final paragraph is not visble, - // update vps.back().end - if (last_row && last_row->next() && - last_row->par() == last_row->next()->par()) { - vps.back().end = last_row->next()->pos(); - } - - return vps; -} - - -namespace { - -struct InsetVisibleInParagraph { - InsetVisibleInParagraph(Inset const & inset) : inset_(inset) {} - bool operator()(VisibleParagraph const & vp) - { - Paragraph * par = vp.par; - InsetList::iterator it = par->insetlist.begin(); - InsetList::iterator end = par->insetlist.end(); - - // Can't refactor this as a functor because we rely on the - // inset_iterator member function getPos(). - for (; it != end; ++it) { - lyx::pos_type const pos = it.getPos(); - if (pos >= vp.start && pos <= vp.end) { - if (it.getInset() == &inset_ || - it.getInset()->getInsetFromID(inset_.id()) != 0) - return true; - } - } - return false; - } - -private: - Inset const & inset_; -}; - -} // namespace anon - - -bool isInsetVisible(Inset const & inset, VPList const & vps) -{ - if (vps.empty()) - return false; - - VPList::const_iterator it = vps.begin(); - VPList::const_iterator end = vps.end(); - - it = std::find_if(it, end, InsetVisibleInParagraph(inset)); - - return it != end; -} diff --git a/src/graphics/GraphicsSupport.h b/src/graphics/GraphicsSupport.h deleted file mode 100644 index 6646b26312..0000000000 --- a/src/graphics/GraphicsSupport.h +++ /dev/null @@ -1,48 +0,0 @@ -// -*- C++ -*- -/** - * \file GraphicsSupport.h - * This file is part of LyX, the document processor. - * Licence details can be found in the file COPYING. - * - * \author Angus Leeming - * - * Full author contact details are available in file CREDITS - */ - -#ifndef GRAPHICSSUPPORT_H -#define GRAPHICSSUPPORT_H - -#include "support/types.h" -#include - -class BufferView; -class Inset; -class Paragraph; - -/** A Paragraph * together with delimiters for the start and end positions - of visibility. - */ -struct VisibleParagraph { - /// - VisibleParagraph() : par(0), start(0), end(0) {} - /// - VisibleParagraph(Paragraph * p, lyx::pos_type s, lyx::pos_type e) - : par(p), start(s), end(e) {} - /// - Paragraph * par; - /// - lyx::pos_type start; - /// - lyx::pos_type end; -}; - - -/// Returns a list of all Paragraphs currently visible in bv. -std::list const getVisibleParagraphs(BufferView const & bv); - -/** Given this data, check whether inset lies within it and is, therefore, - * visible. - */ -bool isInsetVisible(Inset const & inset, std::list const &); - -#endif // GRAPHICSSUPPORT_H diff --git a/src/graphics/LoaderQueue.C b/src/graphics/LoaderQueue.C new file mode 100644 index 0000000000..73062317b6 --- /dev/null +++ b/src/graphics/LoaderQueue.C @@ -0,0 +1,116 @@ +/** + * \file LoaderQueue.C + * This file is part of LyX, the document processor. + * Licence details can be found in the file COPYING. + * + * \author Alfredo Braunstein + * + * Full author contact details are available in file CREDITS + */ + +#include "LoaderQueue.h" + +#include "debug.h" + +#include + +using std::endl; +using std::list; + + +namespace grfx { + + +LoaderQueue & LoaderQueue::get() +{ + static LoaderQueue singleton; + return singleton; +} + + +void LoaderQueue::loadNext() +{ + emptyBucket(); + lyxerr[Debug::GRAPHICS] << "LoaderQueue: " + << cache_queue_.size() + << " items in the queue" << endl; + int counter = 10; + while (cache_queue_.size() && counter--) { + if(cache_queue_.front()->status() == WaitingToLoad) + cache_queue_.front()->startLoading(); + cache_set_.erase(cache_queue_.front()); + cache_queue_.pop_front(); + } + if (cache_queue_.size() || bucket_.size()) { + startLoader(); + } else { + stopLoader(); + } +} + + +LoaderQueue::LoaderQueue() : timer(100, Timeout::ONETIME), + running_(false) +{ + timer.timeout.connect(boost::bind(&LoaderQueue::loadNext, this)); +} + + +void LoaderQueue::emptyBucket() +{ + lyxerr[Debug::GRAPHICS] << "LoaderQueue: emptying bucket" + << endl; + while (! bucket_.empty()) { + addToQueue(bucket_.front()); + bucket_.pop(); + } +} + + +void LoaderQueue::startLoader() +{ + lyxerr[Debug::GRAPHICS] << "LoaderQueue: waking up" << endl; + running_ = true ; + timer.start(); +} + + +void LoaderQueue::stopLoader() +{ + timer.stop(); + running_ = false ; + lyxerr[Debug::GRAPHICS] << "LoaderQueue: I'm going to sleep" << endl; +} + + +bool LoaderQueue::running() const +{ + return running_ ; +} + + +void LoaderQueue::touch(Cache::ItemPtr const & item) +{ + if (! running_) + startLoader(); + bucket_.push(item); +} + + +void LoaderQueue::addToQueue(Cache::ItemPtr const & item) +{ + if (! cache_set_.insert(item).second) { + list::iterator + it = cache_queue_.begin(); + list::iterator + end = cache_queue_.end(); + + it = std::find(it, end, item); + if (it != end) + cache_queue_.erase(it); + } + cache_queue_.push_front(item); +} + + +} // namespace grfx diff --git a/src/graphics/LoaderQueue.h b/src/graphics/LoaderQueue.h new file mode 100644 index 0000000000..aec1c9d7d8 --- /dev/null +++ b/src/graphics/LoaderQueue.h @@ -0,0 +1,69 @@ +// -*- C++ -*- +/** + * \file LoaderQueue.h + * This file is part of LyX, the document processor. + * Licence details can be found in the file COPYING. + * + * \author Alfredo Braunstein + * + * Full author contact details are available in file CREDITS. + * + * This implements a threaded service queue which loads images on background. + * In order to request an image loading you call touch() with the pointer to + * the cached image. Then it will try to satisfy the request as soon as + * posible (that's it: after finishing an eventual loading on progress) + * touch() returns inmediately, in order not tu disrupt the flow of the main + * thread. + * The service thread is the method loadNext(). It's actually not a thread, + * but implemented with a timer that comes back every x msec. + */ + +#ifndef LOADERQUEUE_H +#define LOADERQUEUE_H + +#include "GraphicsCache.h" +#include "GraphicsCacheItem.h" + +#include "frontends/Timeout.h" + +#include +#include + +namespace grfx { + +class LoaderQueue { +public: + //use this to request a loading + void touch(Cache::ItemPtr const & item); + //query if 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(); + //in-progress loading queue (elements are unique here) + std::list cache_queue_; + //makes faster the insertion of new elements + std::set cache_set_; + //newly touched element go here, loadNext move them to cache_queue_ + std::queue bucket_; + // + Timeout timer; + // + bool running_; + //moves bucket_ to cache_queue_ + void emptyBucket(); + //adds or reprioritizes one element in cache_queue_ + void addToQueue(Cache::ItemPtr const & item); + //this is the 'threaded' method, that does the loading in background + void loadNext(); + // + void startLoader(); + // + void stopLoader(); +}; + +} // namespace grfx + +#endif // LOADERQUEUE_H diff --git a/src/graphics/Makefile.am b/src/graphics/Makefile.am index 16313512e9..6a73c0b59d 100644 --- a/src/graphics/Makefile.am +++ b/src/graphics/Makefile.am @@ -17,8 +17,8 @@ libgraphics_la_SOURCES = \ GraphicsLoader.C \ GraphicsParams.C \ GraphicsParams.h \ - GraphicsSupport.h \ - GraphicsSupport.C \ + LoaderQueue.h \ + LoaderQueue.C \ GraphicsTypes.h \ GraphicsTypes.C \ PreviewImage.h \