Alfredo's Loader Queue.

git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@6221 a592a061-630c-0410-9148-cb99ea01b6c8
This commit is contained in:
Angus Leeming 2003-02-21 10:04:08 +00:00
parent 01ae17a24d
commit 546e14eb16
9 changed files with 206 additions and 197 deletions

View File

@ -34,6 +34,9 @@
and a few other (not so) minor things, like and a few other (not so) minor things, like
rewriting most of the LyX kernel. Also current rewriting most of the LyX kernel. Also current
source maintainer. source maintainer.
@bAlfredo Braunstein
@iE-mail: abraunst@libero.it
a (psuedo) threaded graphics loader queue
@bChristian Buescher @bChristian Buescher
user-definable keys, lyxserver and more user-definable keys, lyxserver and more
@bFrancesc Burrull i Mestres @bFrancesc Burrull i Mestres

View File

@ -4,6 +4,10 @@
* examples/de_beispiel_roh.lyx: Small fixes to make it look like a German * examples/de_beispiel_roh.lyx: Small fixes to make it look like a German
document document
2003-02-21 Angus Leeming <leeming@lyx.org>
* CREDITS: Add Alfredo Braunstein.
2003-02-21 Angus Leeming <leeming@lyx.org> 2003-02-21 Angus Leeming <leeming@lyx.org>
* ui/default.ui: change bibkey-insert to bibtem-insert. * ui/default.ui: change bibkey-insert to bibtem-insert.

View File

@ -1,3 +1,11 @@
2003-02-20 Alfredo Braunstein <abraunst@libero.it>
* 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 <leeming@lyx.org> 2003-01-21 Angus Leeming <leeming@lyx.org>
* PreviewLoader.C (dumpPreamble): ensure that \lyxlock does not prevent * PreviewLoader.C (dumpPreamble): ensure that \lyxlock does not prevent

View File

@ -18,7 +18,7 @@
#include "GraphicsCacheItem.h" #include "GraphicsCacheItem.h"
#include "GraphicsImage.h" #include "GraphicsImage.h"
#include "GraphicsParams.h" #include "GraphicsParams.h"
#include "GraphicsSupport.h" #include "LoaderQueue.h"
#include "frontends/LyXView.h" #include "frontends/LyXView.h"
#include "frontends/Timeout.h" #include "frontends/Timeout.h"
@ -66,8 +66,6 @@ private:
/// ///
Params params_; Params params_;
///
Timeout timer;
// Multiple Insets can share the same image // Multiple Insets can share the same image
typedef std::list<Inset const *> InsetList; typedef std::list<Inset const *> InsetList;
/// ///
@ -196,10 +194,8 @@ Image const * Loader::image() const
Loader::Impl::Impl(Params const & params) Loader::Impl::Impl(Params const & params)
: status_(WaitingToLoad), params_(params), : status_(WaitingToLoad), params_(params)
timer(2000, Timeout::ONETIME)
{ {
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) void Loader::Impl::startLoading(Inset const & inset, BufferView const & bv)
{ {
if (status_ != WaitingToLoad || timer.running()) if (status_ != WaitingToLoad)
return; return;
InsetList::const_iterator it = insets.begin(); InsetList::const_iterator it = insets.begin();
@ -303,46 +299,7 @@ void Loader::Impl::startLoading(Inset const & inset, BufferView const & bv)
insets.push_back(&inset); insets.push_back(&inset);
view = bv.owner()->view(); view = bv.owner()->view();
timer.start(); LoaderQueue::get().touch(cached_item_);
}
namespace {
struct FindVisibleInset {
FindVisibleInset(std::list<VisibleParagraph> const & vps) : vps_(vps) {}
bool operator()(Inset const * inset_ptr)
{
if (!inset_ptr)
return false;
return isInsetVisible(*inset_ptr, vps_);
}
private:
std::list<VisibleParagraph> const & vps_;
};
} // namespace anon
void Loader::Impl::checkedLoading()
{
if (insets.empty() || !view.get())
return;
std::list<VisibleParagraph> 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();
} }

View File

@ -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 <config.h>
#include "GraphicsSupport.h"
#include "BufferView.h"
#include "lyxtext.h"
#include "lyxrow.h"
#include "paragraph.h"
#include "frontends/Painter.h"
typedef std::list<VisibleParagraph> 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;
}

View File

@ -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 <list>
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<VisibleParagraph> 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<VisibleParagraph> const &);
#endif // GRAPHICSSUPPORT_H

116
src/graphics/LoaderQueue.C Normal file
View File

@ -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 <boost/bind.hpp>
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<Cache::ItemPtr>::iterator
it = cache_queue_.begin();
list<Cache::ItemPtr>::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

View File

@ -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 <set>
#include <queue>
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::ItemPtr> cache_queue_;
//makes faster the insertion of new elements
std::set<Cache::ItemPtr> cache_set_;
//newly touched element go here, loadNext move them to cache_queue_
std::queue<Cache::ItemPtr> 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

View File

@ -17,8 +17,8 @@ libgraphics_la_SOURCES = \
GraphicsLoader.C \ GraphicsLoader.C \
GraphicsParams.C \ GraphicsParams.C \
GraphicsParams.h \ GraphicsParams.h \
GraphicsSupport.h \ LoaderQueue.h \
GraphicsSupport.C \ LoaderQueue.C \
GraphicsTypes.h \ GraphicsTypes.h \
GraphicsTypes.C \ GraphicsTypes.C \
PreviewImage.h \ PreviewImage.h \