578: Add array2d and tracked_ptr.

2006-09-27 Thierry GERAUD <theo@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 \
participants (1)
-
Thierry GERAUD