URL:
https://svn.lrde.epita.fr/svn/oln/trunk/milena/sandbox
ChangeLog:
2009-09-16 Fabien Freling <fabien.freling(a)lrde.epita.fr>
Add experimental cache support in 2D tiled image.
* fabien/mln/core/image/cache.hh: Implement cache management.
* fabien/mln/core/image/page.hh: Implement page management.
* fabien/mln/core/image/tiled2d.hh: Add cache management.
* fabien/tests/core/image/Makefile: Minor update.
* fabien/tests/core/image/tiled2d.cc: Minor update.
---
mln/core/image/cache.hh | 159 ++++++++++++++++++++++++++++++++++++++++++++
mln/core/image/page.hh | 155 ++++++++++++++++++++++++++++++++++++++++++
mln/core/image/tiled2d.hh | 37 ++++++----
tests/core/image/Makefile | 2
tests/core/image/tiled2d.cc | 7 +
5 files changed, 345 insertions(+), 15 deletions(-)
Index: trunk/milena/sandbox/fabien/tests/core/image/tiled2d.cc
===================================================================
--- trunk/milena/sandbox/fabien/tests/core/image/tiled2d.cc (revision 4489)
+++ trunk/milena/sandbox/fabien/tests/core/image/tiled2d.cc (revision 4490)
@@ -43,10 +43,13 @@
mln_piter_(tiled2d<rgb8>) p(tiled_ima.domain());
for_all(p)
- if (p.col() % 16 == 0)
+ if (p.row() % 7 == 0)
+ {
+ //std::cout << tiled_ima(p);
tiled_ima(p) = literal::green;
- //std::cout << tiled_ima(p) << std::endl;
+ //std::cout << " -> " << tiled_ima(p) << std::endl;
//mln_assertion(tiled_ima(p) == ima(p));
+ }
/*for_all(p)
if (p.col() % 16 == 0)
Index: trunk/milena/sandbox/fabien/tests/core/image/Makefile
===================================================================
--- trunk/milena/sandbox/fabien/tests/core/image/Makefile (revision 4489)
+++ trunk/milena/sandbox/fabien/tests/core/image/Makefile (revision 4490)
@@ -3,5 +3,7 @@
LIBS = `Magick++-config --cppflags --cxxflags --ldflags --libs`
INC = -I../../../ -I../../../../../
+all: tiled2d
+
tiled2d: tiled2d.cc
${CXX} ${CXXFLAGS} ${INC} $^ -o tiled2d
Index: trunk/milena/sandbox/fabien/mln/core/image/cache.hh
===================================================================
--- trunk/milena/sandbox/fabien/mln/core/image/cache.hh (revision 0)
+++ trunk/milena/sandbox/fabien/mln/core/image/cache.hh (revision 4490)
@@ -0,0 +1,159 @@
+// Copyright (C) 2009 EPITA Research and Development Laboratory (LRDE)
+//
+// This file is part of Olena.
+//
+// Olena is free software: you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation, version 2 of the License.
+//
+// Olena is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Olena. If not, see <http://www.gnu.org/licenses/>.
+//
+// As a special exception, you may use this file as part of a free
+// software project without restriction. Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to produce
+// an executable, this file does not by itself cause the resulting
+// executable to be covered by the GNU General Public License. This
+// exception does not however invalidate any other reasons why the
+// executable file might be covered by the GNU General Public License.
+
+#ifndef MLN_CORE_IMAGE_CACHE_HH
+# define MLN_CORE_IMAGE_CACHE_HH
+
+/// \file
+/// Definition of the basic mln::cache class.
+
+#include <mln/util/array.hh>
+
+#include <mln/core/image/page.hh>
+
+
+namespace mln
+{
+
+ template <typename D, typename V>
+ class cache
+ {
+ public:
+
+ // Constructor
+ cache(D domain, std::streampos pos, unsigned ncols, std::fstream* f);
+ ~cache();
+
+ void set_number_pages(unsigned number_pages);
+ V read(mln_psite(D) p);
+ void write(const mln_psite(D)& p, const V& value);
+
+ protected:
+
+ util::array<page<D, V>* > pages_;
+ unsigned number_pages_;
+
+ // Image info.
+ D domain_;
+ std::streampos pos_;
+ unsigned ncols_;
+ std::fstream* f_;
+ };
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+
+ template <typename D, typename V>
+ inline
+ cache<D, V>::cache(D domain, std::streampos pos, unsigned ncols, std::fstream*
f)
+ {
+ this->number_pages_ = 1;
+
+ this->domain_ = domain;
+ this->pos_ = pos;
+ this->ncols_ = ncols;
+ this->f_ = f;
+ }
+
+ template <typename D, typename V>
+ inline
+ cache<D, V>::~cache()
+ {
+ for (unsigned i = 0; i < this->pages_.nelements(); ++i)
+ delete this->pages_[i];
+ this->pages_.clear();
+ }
+
+ template <typename D, typename V>
+ inline
+ void
+ cache<D, V>::set_number_pages(unsigned number_pages)
+ {
+ if (number_pages < this->number_pages_)
+ {
+ // FIXME: Prune pages array.
+ }
+ this->number_pages_ = number_pages;
+ }
+
+ template <typename D, typename V>
+ inline
+ V
+ cache<D, V>::read(mln_psite(D) p)
+ {
+ for (unsigned i = 0; i < this->pages_.nelements(); ++i)
+ {
+ if (this->pages_[i]->has(p))
+ return this->pages_[i]->read(p);
+ }
+
+ // If we have not found a valid page, we just add one.
+ // FIXME: We should test that we have room for a new page.
+ page<D, V>* new_page = new page<D, V>(this->domain_,
+ p,
+ this->pos_,
+ this->ncols_,
+ this->f_);
+ this->pages_.append(new_page);
+ return new_page->read(p);
+ }
+
+ template <typename D, typename V>
+ inline
+ void
+ cache<D, V>::write(const mln_psite(D)& p, const V& value)
+ {
+ bool found = false;
+ for (unsigned i = 0; !found && i < this->pages_.nelements(); ++i)
+ {
+ if (this->pages_[i]->has(p))
+ {
+ this->pages_[i]->write(p, value);
+ found = true;
+ }
+ }
+
+ if (!found)
+ {
+ // If we have not found a valid page, we just add one.
+ // FIXME: We should test that we have room for a new page.
+ page<D, V>* new_page = new page<D, V>(this->domain_,
+ p,
+ this->pos_,
+ this->ncols_,
+ this->f_);
+ this->pages_.append(new_page);
+ new_page->write(p, value);
+ }
+ }
+
+
+# endif // ! MLN_INCLUDE_ONLY
+
+} // end of namespace mln
+
+
+#endif // ! MLN_CORE_IMAGE_CACHE_HH
Index: trunk/milena/sandbox/fabien/mln/core/image/tiled2d.hh
===================================================================
--- trunk/milena/sandbox/fabien/mln/core/image/tiled2d.hh (revision 4489)
+++ trunk/milena/sandbox/fabien/mln/core/image/tiled2d.hh (revision 4490)
@@ -39,6 +39,8 @@
# include <mln/fun/i2v/all_to.hh>
# include <mln/value/proxy.hh>
+# include <mln/core/image/cache.hh>
+
namespace mln
@@ -63,6 +65,7 @@
std::string file_;
bool loaded_;
T value_;
+ cache<box2d, T>* cache_;
box2d b_; // theoretical box
unsigned bdr_;
@@ -323,8 +326,11 @@
data< tiled2d<T> >::deallocate_()
{
if (this->loaded_)
+ {
+ delete this->cache_;
this->f_->close();
}
+ }
template <typename T>
inline
@@ -428,13 +434,18 @@
{
this_->data_->f_ = new std::fstream(this->data_->file_.c_str());
this_->data_->loaded_ = true;
+ this_->data_->cache_ = new cache<box2d, T>(this_->data_->b_,
+ this_->data_->pos_,
+ this_->ncols(),
+ this_->data_->f_);
}
- std::streampos offset = this_->data_->pos_;
+ /*std::streampos offset = this_->data_->pos_;
offset += (this_->ncols() * p.row() + p.col()) * sizeof(T);
this_->data_->f_->seekg(offset);
this_->data_->f_->get((char*)(&this_->data_->value_), sizeof(T) +
1); // FIXME: I don't know why
// I have to add +1.
- return this_->data_->value_;
+ return this_->data_->value_;*/
+ return this_->data_->cache_->read(p);
}
template <typename T>
@@ -442,15 +453,17 @@
void
tiled2d<T>::write_(const point2d& p, const T& value)
{
- if (!this->data_->loaded_)
+ mln::tiled2d<T>* this_ = const_cast<mln::tiled2d<T>* >(this); //
Trust me, I have to do this(_).
+ if (!this_->data_->loaded_)
{
- this->data_->f_ = new std::fstream(this->data_->file_.c_str());
- this->data_->loaded_ = true;
+ this_->data_->f_ = new std::fstream(this->data_->file_.c_str());
+ this_->data_->loaded_ = true;
+ this_->data_->cache_ = new cache<box2d, T>(this_->data_->b_,
+ this_->data_->pos_,
+ this_->ncols(),
+ this_->data_->f_);
}
- std::streampos offset = this->data_->pos_;
- offset += (this->ncols() * p.row() + p.col()) * sizeof(T);
- this->data_->f_->seekp(offset);
- this->data_->f_->write((char*)(&value), sizeof(T));
+ this_->data_->cache_->write(p, value);
}
@@ -462,8 +475,7 @@
tiled2d<T>::at_(unsigned row, unsigned col) const
{
mln_precondition(this->has(point2d(row, col)));
- //FIXME: use the cache Luke.
- return this->data_->value_;
+ return this->data_->cache_(point2d(row, col));
}
template <typename T>
@@ -472,8 +484,7 @@
tiled2d<T>::at_(unsigned row, unsigned col)
{
mln_precondition(this->has(point2d(row, col)));
- //FIXME: use the cache Luke.
- return this->data_->value_;
+ return this->data_->cache_(point2d(row, col));
}
template <typename T>
Index: trunk/milena/sandbox/fabien/mln/core/image/page.hh
===================================================================
--- trunk/milena/sandbox/fabien/mln/core/image/page.hh (revision 0)
+++ trunk/milena/sandbox/fabien/mln/core/image/page.hh (revision 4490)
@@ -0,0 +1,155 @@
+// Copyright (C) 2009 EPITA Research and Development Laboratory (LRDE)
+//
+// This file is part of Olena.
+//
+// Olena is free software: you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation, version 2 of the License.
+//
+// Olena is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Olena. If not, see <http://www.gnu.org/licenses/>.
+//
+// As a special exception, you may use this file as part of a free
+// software project without restriction. Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to produce
+// an executable, this file does not by itself cause the resulting
+// executable to be covered by the GNU General Public License. This
+// exception does not however invalidate any other reasons why the
+// executable file might be covered by the GNU General Public License.
+
+#ifndef MLN_CORE_IMAGE_PAGE_HH
+# define MLN_CORE_IMAGE_PAGE_HH
+
+/// \file
+/// Definition of the basic mln::page class.
+
+# include <fstream>
+
+# include <mln/util/array.hh>
+
+
+namespace mln
+{
+
+ template <typename D, typename V>
+ class page
+ {
+ public:
+
+ // Constructor & destructor.
+ page(D domain, mln_psite(D) p, std::streampos pos, unsigned ncols, std::fstream*
f);
+ ~page();
+
+ bool has(mln_psite(D) p);
+ V read(mln_psite(D) p);
+ void write(const mln_psite(D)& p, const V& value);
+ void flush();
+
+ // Debug.
+ void print_buffer();
+
+ protected:
+
+ D domain_;
+ D range_;
+ V* buffer_;
+ std::fstream* f_;
+ std::streampos offset_;
+ unsigned buffer_size_;
+ };
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+
+ template <typename D, typename V>
+ inline
+ page<D, V>::page(D domain, mln_psite(D) p, std::streampos pos, unsigned ncols,
std::fstream* f)
+ {
+ // Defining layout for a line.
+ this->range_.pmin() = p;
+ this->range_.pmin().col() = domain.pmin().col();
+ this->range_.pmax() = p;
+ this->range_.pmax().col() = domain.pmax().col();
+
+ this->buffer_ = new V[ncols];
+
+ this->domain_ = domain;
+ this->f_ = f;
+ this->buffer_size_ = ncols;
+
+ this->offset_ = pos;
+ this->offset_ += (ncols * p.row()) * sizeof(V);
+ f->seekg(this->offset_);
+ f->get((char*)(buffer_), buffer_size_ * sizeof(V));
+ }
+
+ template <typename D, typename V>
+ inline
+ page<D, V>::~page()
+ {
+ this->flush();
+ delete this->buffer_;
+ }
+
+ template <typename D, typename V>
+ inline
+ bool
+ page<D, V>::has(mln_psite(D) p)
+ {
+ return p.col() >= this->range_.pmin().col() &&
+ p.col() <= this->range_.pmax().col() &&
+ p.row() >= this->range_.pmin().row() &&
+ p.row() <= this->range_.pmax().row();
+ }
+
+ template <typename D, typename V>
+ inline
+ V
+ page<D, V>::read(mln_psite(D) p)
+ {
+ return buffer_[p.col() - this->range_.pmin().col()];
+ }
+
+ template <typename D, typename V>
+ inline
+ void
+ page<D, V>::write(const mln_psite(D)& p, const V& value)
+ {
+ buffer_[p.col() - this->range_.pmin().col()] = value;
+ }
+
+ template <typename D, typename V>
+ inline
+ void
+ page<D, V>::flush()
+ {
+ this->f_->seekg(this->offset_);
+ this->f_->write((char*)(buffer_), buffer_size_ * sizeof(V));
+ }
+
+
+ // Debug.
+
+ template <typename D, typename V>
+ inline
+ void
+ page<D, V>::print_buffer()
+ {
+ for (unsigned i = 0; i < this->buffer_size_; ++i)
+ std::cout << "buffer[" << i << "] = "
<< this->buffer_[i] << std::endl;
+ }
+
+
+# endif // ! MLN_INCLUDE_ONLY
+
+} // end of namespace mln
+
+
+#endif // ! MLN_CORE_IMAGE_PAGE_HH