2006-09-27 Thierry GERAUD <theo(a)tegucigalpa.lrde.epita.fr>
Add array2d and tracked_ptr.
* oln/core/2d/array2d.hh: New.
This file also provides the tracked_ptr class which should be
moved later in a more appropriate file.
* oln/core/2d/image2d.hh (lvalue_type, is_mutable_type): Add.
(data_): New attribute.
(impl_op_read): Update; code is no more fake.
(impl_op_readwrite): New.
(image2d): Update.
* oln/Makefile.am (nobase_oln_HEADERS): Update; remove
the core/2d/grid2d.hh duplicate.
Index: oln/core/2d/array2d.hh
===================================================================
--- oln/core/2d/array2d.hh (revision 0)
+++ oln/core/2d/array2d.hh (revision 0)
@@ -0,0 +1,313 @@
+// Copyright (C) 2001, 2003, 2004, 2006 EPITA Research and Development
+// Laboratory
+//
+// This file is part of the Olena Library. This library is free
+// software; you can redistribute it and/or modify it under the terms
+// of the GNU General Public License version 2 as published by the
+// Free Software Foundation.
+//
+// This library 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 this library; see the file COPYING. If not, write to
+// the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+// Boston, MA 02111-1307, USA.
+//
+// As a special exception, you may use this file as part of a free
+// software library 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 OLENA_CORE_2D_ARRAY2D_HH
+# define OLENA_CORE_2D_ARRAY2D_HH
+
+# include <cstdlib>
+# include <set>
+# include <mlc/contract.hh>
+
+
+namespace oln
+{
+
+ template <typename T>
+ struct tracked_ptr
+ {
+ typedef tracked_ptr<T> self_t;
+ typedef std::set<self_t*> holders_t;
+
+ T* ptr_;
+ holders_t* holders_;
+
+ /// Coercion towards Boolean (for arithmetical tests).
+ operator bool() const
+ {
+ invariant_();
+ return ptr_ != 0;
+ }
+
+ /// Negation (for arithmetical tests).
+ bool operator not() const
+ {
+ invariant_();
+ return not bool(*this);
+ }
+
+ /*! \brief Mimics the behavior of op-> for a pointer in the const case.
+ **
+ ** \invariant Pointer proxy exists.
+ */
+ const T*const operator->() const
+ {
+ invariant_();
+ precondition(ptr_ != 0);
+ return ptr_;
+ }
+
+ /*! \brief Mimics the behavior of op-> for a pointer in the mutable case.
+ **
+ ** \invariant Pointer proxy exists.
+ */
+ T*const operator->()
+ {
+ invariant_();
+ precondition(ptr_ != 0);
+ return ptr_;
+ }
+
+ /// Ctor.
+ tracked_ptr() :
+ ptr_(0),
+ holders_(0)
+ {
+ invariant_();
+ }
+
+ /// Ctor.
+ tracked_ptr(T* ptr) :
+ ptr_(ptr)
+ {
+ if (ptr == 0)
+ holders_ = 0;
+ else
+ {
+ holders_ = new holders_t;
+ holders_->insert(this);
+ }
+ invariant_();
+ }
+
+ /// Cpy ctor.
+ tracked_ptr(const self_t& rhs) :
+ ptr_(rhs.ptr_),
+ holders_(rhs.holders_)
+ {
+ rhs.invariant_();
+ if (ptr_ != 0)
+ holders_->insert(this);
+ invariant_();
+ }
+
+ /// Assignment.
+ self_t& operator=(const self_t& rhs)
+ {
+ invariant_();
+ rhs.invariant_();
+ if (&rhs == this or rhs.ptr_ == ptr_)
+ // no-op
+ return *this;
+ clean_();
+ ptr_ = rhs.ptr_;
+ holders_ = rhs.holders_;
+ holders_->insert(this);
+ return *this;
+ }
+
+ /// Assignment.
+ self_t& operator=(T* ptr)
+ {
+ invariant_();
+ if (ptr == ptr_)
+ // no-op
+ return *this;
+ clean_();
+ ptr_ = ptr;
+ if (ptr == 0)
+ holders_ = 0;
+ else
+ {
+ holders_ = new holders_t;
+ holders_->insert(this);
+ }
+ return *this;
+ }
+
+ /// Dtor.
+ ~tracked_ptr()
+ {
+ clean_();
+ }
+
+ void invariant_() const
+ {
+ invariant((ptr_ and holders_) or (not ptr_ and not holders_));
+ if (ptr_ == 0)
+ return;
+ invariant(holders_->size() > 0);
+ self_t* this_ = const_cast<self_t*>(this);
+ invariant(holders_->find(this_) != holders_->end());
+ typename holders_t::const_iterator i;
+ for (i = holders_->begin(); i != holders_->end(); ++i)
+ invariant((*i)->ptr_ == ptr_);
+ }
+
+ void clean_()
+ {
+ invariant_();
+ if (ptr_ == 0)
+ // no-op
+ return;
+ if (holders_->size() == 1)
+ {
+ delete ptr_;
+ delete holders_;
+ }
+ else
+ holders_->erase(this);
+ ptr_ = 0;
+ holders_ = 0;
+ invariant_();
+ }
+
+ friend std::ostream& operator<<(std::ostream& ostr, const self_t&
tp)
+ {
+ ostr << "tracked_ptr @ " << (&tp)
+ << " { ptr = " << tp.ptr_
+ << " / holders = ";
+ if (tp.holders_ == 0)
+ ostr << "0";
+ else
+ {
+ typename holders_t::const_iterator i;
+ for (i = tp.holders_->begin(); i != tp.holders_->end(); ++i)
+ ostr << (*i) << ' ';
+ }
+ ostr << " }";
+ return ostr;
+ }
+ };
+
+
+ /// General 2D array class.
+ template <typename value_t, typename coord_t = int>
+ class array2d
+ {
+ public:
+
+ /// Ctor.
+ array2d(coord_t imin, coord_t jmin,
+ coord_t imax, coord_t jmax) :
+ imin_(imin),
+ jmin_(jmin),
+ imax_(imax),
+ jmax_(jmax)
+ {
+ precondition(imax >= imin and jmax >= jmin);
+ ilen_ = imax - imin + 1;
+ jlen_ = jmax - jmin + 1;
+ allocate_();
+ }
+
+ /// Ctor.
+ array2d(coord_t ilen, coord_t jlen) :
+ imin_(0),
+ jmin_(0),
+ ilen_(ilen),
+ jlen_(jlen)
+ {
+ precondition(ilen > 0 and jlen > 0);
+ imax_ = imin_ + ilen_;
+ jmax_ = jmin_ + ilen_;
+ allocate_();
+ }
+
+ /// Dtor.
+ ~array2d()
+ {
+ deallocate_();
+ }
+
+ value_t operator()(coord_t i, coord_t j) const
+ {
+ precondition(has(i, j));
+ return array_[i][j];
+ }
+
+ value_t& operator()(coord_t i, coord_t j)
+ {
+ precondition(has(i, j));
+ return array_[i][j];
+ }
+
+ bool has(coord_t i, coord_t j) const
+ {
+ return
+ i >= imin_ and i <= imax_ and
+ j >= jmin_ and j <= jmax_;
+ }
+
+ size_t memsize() const
+ {
+ return
+ // buffer_
+ size_t(ilen_) * size_t(jlen_) * sizeof(value_t)
+ +
+ // array_
+ size_t(ilen_) * sizeof(value_t*);
+ }
+
+ protected:
+
+ coord_t imin_, jmin_, imax_, jmax_;
+ coord_t ilen_, jlen_;
+ value_t* buffer_;
+ value_t** array_;
+
+ private:
+
+ void allocate_()
+ {
+ buffer_ = new value_t[size_t(ilen_) * size_t(jlen_)];
+ array_ = new value_t*[size_t(ilen_)];
+ value_t* buf = buffer_ - jmin_;
+ for (coord_t i = 0; i < ilen_; ++i)
+ {
+ array_[i] = buf;
+ buf += jlen_;
+ }
+ array_ -= imin_;
+ }
+
+ void deallocate_()
+ {
+ precondition(buffer_ != 0 and array_ != 0);
+ delete[] buffer_;
+ buffer_ = 0; // safety
+ array_ += imin_;
+ delete[] array_;
+ array_ = 0; // safety
+ }
+ };
+
+
+} // end of namespace oln
+
+
+#endif // ! OLENA_CORE_2D_ARRAY2D_HH
Index: oln/core/2d/image2d.hh
===================================================================
--- oln/core/2d/image2d.hh (revision 577)
+++ oln/core/2d/image2d.hh (working copy)
@@ -30,6 +30,7 @@
# define OLENA_CORE_2D_IMAGE2D_HH
# include <oln/core/image_entry.hh>
+# include <oln/core/2d/array2d.hh>
namespace oln
@@ -52,6 +53,8 @@
typedef bkd_piter_bbox_<topo_type> bkd_piter_type;
typedef T value_type;
+ typedef T lvalue_type;
+ typedef mlc::true_ is_mutable_type;
typedef image2d<T> real_type;
};
@@ -71,12 +74,16 @@
class image2d : public image_entry< image2d<T> >
{
typedef image2d<T> self_t;
+ typedef array2d<T> array_t;
public:
/// Ctor.
image2d(unsigned nrows, unsigned ncols, unsigned border = 2)
- : topo_( bbox2d( point2d(0,0), point2d(nrows-1, ncols-1)), border )
+ : topo_(bbox2d(point2d(0, 0),
+ point2d(nrows-1, ncols-1)),
+ border),
+ data_(new array_t(0, 0, nrows-1, ncols-1))
{
}
@@ -87,19 +94,22 @@
T impl_op_read(const point2d& p) const
{
- return (T)(void*)this;
-// static T val_;
-// return ++val_;
+ precondition(data_ != 0);
+ precondition(topo_.has_large(p));
+ return data_->operator()(p.row(), p.col());
}
- bool impl_has(const point2d& p) const
+ T& impl_op_readwrite(const point2d& p)
{
- return true;
+ precondition(data_ != 0);
+ precondition(topo_.has_large(p));
+ return data_->operator()(p.row(), p.col());
}
private:
topo2d topo_;
+ tracked_ptr<array_t> data_;
};
Index: oln/Makefile.am
===================================================================
--- oln/Makefile.am (revision 577)
+++ oln/Makefile.am (working copy)
@@ -15,8 +15,8 @@
\
core/1d/grid1d.hh \
\
- core/2d/grid2d.hh \
core/2d/aliases.hh \
+ core/2d/array2d.hh \
core/2d/dpoint2d.hh \
core/2d/grid2d.hh \
core/2d/image2d.hh \