675: Add a morpher to count read-write ops.
2006-10-24 Thierry GERAUD <theo@tegucigalpa.lrde.epita.fr> Add a morpher to count read-write ops. * tests/morphers/count_rw_morpher.cc: New. * tests/morphers/Makefile.am: Update. * oln/morpher/count_rw.hh: New. * oln/value/proxy.hh: New. * oln/value/rw_counter.hh: New. * oln/Makefile.am: Update. * oln/core/traits_id.hh (unop_vproxy, binop_vproxy): New. (others): Update. * oln/core/typedefs.hh (oln_is_computed, oln_is_computed_): New. * oln/morpher/internal/image_value_morpher.hh (image_value_morpher): New overloading for ctor. (image_): Add & to its type. Index: tests/morphers/count_rw_morpher.cc =================================================================== --- tests/morphers/count_rw_morpher.cc (revision 0) +++ tests/morphers/count_rw_morpher.cc (revision 0) @@ -0,0 +1,53 @@ +// Copyright (C) 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. + +/// Test the count_rw morpher. + +#include <cassert> +#include <oln/basics2d.hh> +#include <oln/morpher/count_rw.hh> + + +int main() +{ + using namespace oln; + + typedef image2d<int> image_t; + image_t ima(3,3); + morpher::count_rw<image_t> ima2(ima); + point2d p(0,0); + + ima2(p); + ima2(p) = 51; + int i = ima2(p); + i = 0; // suppress "unused i" warning + + assert(value::counter::n_readwrite_calls(ima) == 3); + assert(value::counter::n_readonly_calls(ima) == 0); + assert(value::counter::n_reads(ima) == 1); + assert(value::counter::n_writes(ima) == 1); +} Index: tests/morphers/Makefile.am =================================================================== --- tests/morphers/Makefile.am (revision 674) +++ tests/morphers/Makefile.am (working copy) @@ -21,6 +21,7 @@ check_PROGRAMS = \ identity_morpher \ add_neighborhood_morpher \ + count_rw_morpher \ slice_morpher \ stack_morpher \ value_cast \ @@ -31,6 +32,7 @@ # Morphers. identity_morpher_SOURCES = identity_morpher.cc add_neighborhood_morpher_SOURCES = add_neighborhood_morpher.cc +count_rw_morpher_SOURCES = count_rw_morpher.cc slice_morpher_SOURCES = slice_morpher.cc stack_morpher_SOURCES = stack_morpher.cc value_cast_SOURCES = value_cast.cc Index: oln/core/traits_id.hh =================================================================== --- oln/core/traits_id.hh (revision 674) +++ oln/core/traits_id.hh (working copy) @@ -37,12 +37,22 @@ namespace id { + /// \{ + /// Generic identifiers for operators. + enum { + unop_vproxy = 1, + binop_vproxy = 1 + }; + + /// \} + + /// \{ /// Identifiers for oln binary operators +. enum { - op_plus_pointnd_dpointnd = 1 + op_plus_pointnd_dpointnd = 2 }; /// \} @@ -53,8 +63,8 @@ /// Identifiers for oln binary operators -. enum { - op_minus_pointnd_pointnd = 1, - op_minus_pointnd_dpointnd = 2 + op_minus_pointnd_pointnd = 2, + op_minus_pointnd_dpointnd = 3 }; /// \} @@ -65,7 +75,7 @@ /// Identifiers for oln unary operators -. enum { - op_uminus_dpointnd = 1 + op_uminus_dpointnd = 2 }; /// \} Index: oln/core/typedefs.hh =================================================================== --- oln/core/typedefs.hh (revision 674) +++ oln/core/typedefs.hh (working copy) @@ -227,6 +227,9 @@ # define oln_dpoint(T) oln_type_of(T, dpoint) # define oln_dpoint_(T) oln_type_of_(T, dpoint) +# define oln_is_computed(T) oln_type_of(T, is_computed) +# define oln_is_computed_(T) oln_type_of_(T, is_computed) + # define oln_value(T) oln_type_of(T, value) # define oln_value_(T) oln_type_of_(T, value) Index: oln/Makefile.am =================================================================== --- oln/Makefile.am (revision 674) +++ oln/Makefile.am (working copy) @@ -170,6 +170,7 @@ morpher/internal/image_value_morpher.hh \ \ morpher/add_neighborhood.hh \ + morpher/count_rw.hh \ morpher/fwd_decls.hh \ morpher/identity.hh \ morpher/tags.hh \ @@ -186,6 +187,8 @@ value/all.hh \ value/default.hh \ value/greylevel.hh \ + value/proxy.hh \ + value/rw_counter.hh \ value/tags.hh \ \ basics1d.hh \ Index: oln/morpher/internal/image_value_morpher.hh =================================================================== --- oln/morpher/internal/image_value_morpher.hh (revision 674) +++ oln/morpher/internal/image_value_morpher.hh (working copy) @@ -88,13 +88,15 @@ { public: - // FIXME: Handle the constness. + // FIXME: Hack here; constness should be properly handled. image_value_morpher(const Image& image); + image_value_morpher(Image& image); + const Image& delegate() const; Image& delegate(); protected: - Image image_; + Image& image_; }; @@ -103,6 +105,12 @@ template <typename Image, typename Exact> image_value_morpher<Image, Exact>::image_value_morpher(const Image& image) : + image_(const_cast<Image&>(image)) + { + } + + template <typename Image, typename Exact> + image_value_morpher<Image, Exact>::image_value_morpher(Image& image) : image_(image) { } Index: oln/morpher/count_rw.hh =================================================================== --- oln/morpher/count_rw.hh (revision 0) +++ oln/morpher/count_rw.hh (revision 0) @@ -0,0 +1,156 @@ +// Copyright (C) 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 OLN_MORPHER_COUNT_RW_HH +# define OLN_MORPHER_COUNT_RW_HH + +# include <oln/value/rw_counter.hh> +# include <oln/morpher/internal/image_value_morpher.hh> + + +namespace oln +{ + + + namespace morpher + { + // Forward declaration. + template <typename Image> struct count_rw; + + } // end of namespace oln::morpher + + + /// Super type. + template <typename Image> + struct set_super_type< morpher::count_rw<Image> > + { + typedef morpher::count_rw<Image> self_t; + typedef morpher::internal::image_value_morpher<Image, self_t> ret; + }; + + + template <typename Image> + struct vtypes< morpher::count_rw<Image> > + { + public: + typedef mlc::true_ is_computed_type; + + typedef oln_value(Image) value_type; + typedef value::rw_counter<Image> lvalue_type; + }; + + template <typename Image> + struct single_vtype< morpher::count_rw<Image>, typedef_::rvalue_type > + { + typedef value::ro_counter<Image> ret; + }; + + + + namespace morpher + { + + /// 'Image thru Function' morpher. + template <typename Image> + class count_rw : public internal::image_value_morpher< Image, + morpher::count_rw<Image> > + { + private: + + typedef count_rw<Image> self_t; + typedef internal::image_value_morpher<Image, self_t> super_t; + + using super_t::image_; + + public: + + count_rw(Image& image); + count_rw(oln::abstract::mutable_image<Image>& image); + + oln_rvalue(self_t) impl_op_read(const oln_psite(self_t)& p) const; + oln_lvalue(self_t) impl_op_readwrite(const oln_psite(self_t)& p); + }; + + + namespace ERROR + { + + struct FIXME; + + } // end of namespace oln::morpher::ERROR + + +# ifndef OLN_INCLUDE_ONLY + + // public + + template <typename Image> + count_rw<Image>::count_rw(Image& image) : + super_t(image) + { + } + + template <typename Image> + count_rw<Image>::count_rw(oln::abstract::mutable_image<Image>& image) : + super_t(image.exact()) + { + } + + template <typename Image> + oln_rvalue(count_rw<Image>) + count_rw<Image>::impl_op_read(const oln_psite(count_rw<Image>)& p) const + { + value::ro_counter<Image> tmp(image_, p); + return tmp; + } + + template <typename Image> + oln_lvalue(count_rw<Image>) + count_rw<Image>::impl_op_readwrite(const oln_psite(count_rw<Image>)& p) + { + value::rw_counter<Image> tmp(image_, p); + return tmp; + } + +# endif + + } // end of namespace oln::morpher + + + template <typename I> + morpher::count_rw<I> + count_rw(oln::abstract::mutable_image<I>& input) + { + morpher::count_rw<I> tmp(input.exact()); + return tmp; + } + + +} // end of namespace oln + + +#endif // ! OLN_MORPHER_COUNT_RW_HH Index: oln/value/proxy.hh =================================================================== --- oln/value/proxy.hh (revision 0) +++ oln/value/proxy.hh (revision 0) @@ -0,0 +1,472 @@ +// Copyright (C) 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 OLN_CORE_VALUE_PROXY_HH +# define OLN_CORE_VALUE_PROXY_HH + +# include <xtd/optraits.hh> +# include <oln/core/type.hh> +# include <oln/core/traits_id.hh> + + +namespace oln +{ + + + namespace value + { + + namespace abstract + { + + template <typename E> + struct proxy : public virtual stc::any__simple<E>, + public oln::type + { + protected: + proxy(); + }; + + +# ifndef OLN_INCLUDE_ONLY + + template <typename E> + proxy<E>::proxy() + { + } + +# endif + + } // end of namespace oln::value::abstract + + + } // end of namespace oln::value + + + + // Traits. + //--------------------------- + + + /// unary op on a value proxy + template <typename name, typename T> + struct case_ < xtd::op_<name>, T, + oln::id::unop_vproxy > + : where_< mlc_is_a(T, value::abstract::proxy) > + { + struct protected_ { + typedef typename T::value_type V; + typedef xtd_unop_trait(xtd::op_<name>, V) ret; + }; + }; + + + /// binary op involving at least one value proxy + template <typename name, typename T1, typename T2> + struct case_ < xtd::op_<name>, mlc::pair_<T1,T2>, + oln::id::binop_vproxy > + : where_< mlc::or_< mlc_is_a(T1, value::abstract::proxy), + mlc_is_a(T2, value::abstract::proxy) > > + { + template <typename T> + struct value_type + { + typedef mlc_typedef(T, value_type) V; + typedef typename mlc::if_< mlc_is_found(V), V, T >::ret ret; + }; + struct protected_ { + typedef mlc_ret(value_type<T1>) V1; + typedef mlc_ret(value_type<T2>) V2; + typedef xtd_binop_trait(xtd::op_<name>, V1, V2) ret; + }; + }; + + + + // Unary ops. + //--------------------------- + + + // Op -. + template <typename P> + xtd_op_uminus_trait(P) operator - (const value::abstract::proxy<P>& val); + // Op not. + template <typename P> + xtd_op_lnot_trait(P) operator not (const value::abstract::proxy<P>& val); + + // FIXME: To be continued. + + + + // Binary ops. + //--------------------------- + + // Op +. + template <typename P, typename V> + xtd_op_plus_trait(P, V) operator + (const value::abstract::proxy<P>& lhs, const V& rhs); + template <typename V, typename P> + xtd_op_plus_trait(V, P) operator + (const V& lhs, const value::abstract::proxy<P>& rhs); + // Op -. + template <typename P, typename V> + xtd_op_minus_trait(P, V) operator - (const value::abstract::proxy<P>& lhs, const V& rhs); + template <typename V, typename P> + xtd_op_minus_trait(V, P) operator - (const V& lhs, const value::abstract::proxy<P>& rhs); + // Op *. + template <typename P, typename V> + xtd_op_mult_trait(P, V) operator * (const value::abstract::proxy<P>& lhs, const V& rhs); + template <typename V, typename P> + xtd_op_mult_trait(V, P) operator * (const V& lhs, const value::abstract::proxy<P>& rhs); + // Op /. + template <typename P, typename V> + xtd_op_div_trait(P, V) operator / (const value::abstract::proxy<P>& lhs, const V& rhs); + template <typename V, typename P> + xtd_op_div_trait(V, P) operator / (const V& lhs, const value::abstract::proxy<P>& rhs); + // Op %. + template <typename P, typename V> + xtd_op_mod_trait(P, V) operator % (const value::abstract::proxy<P>& lhs, const V& rhs); + template <typename V, typename P> + xtd_op_mod_trait(V, P) operator % (const V& lhs, const value::abstract::proxy<P>& rhs); + + // Op ==. + template <typename P, typename V> + xtd_op_eq_trait(P, V) operator == (const value::abstract::proxy<P>& lhs, const V& rhs); + template <typename V, typename P> + xtd_op_eq_trait(V, P) operator == (const V& lhs, const value::abstract::proxy<P>& rhs); + // Op !=. + template <typename P, typename V> + xtd_op_neq_trait(P, V) operator != (const value::abstract::proxy<P>& lhs, const V& rhs); + template <typename V, typename P> + xtd_op_neq_trait(V, P) operator != (const V& lhs, const value::abstract::proxy<P>& rhs); + + // Op <. + template <typename P, typename V> + xtd_op_less_trait(P, V) operator < (const value::abstract::proxy<P>& lhs, const V& rhs); + template <typename V, typename P> + xtd_op_less_trait(V, P) operator < (const V& lhs, const value::abstract::proxy<P>& rhs); + // Op <=. + template <typename P, typename V> + xtd_op_leq_trait(P, V) operator <= (const value::abstract::proxy<P>& lhs, const V& rhs); + template <typename V, typename P> + xtd_op_leq_trait(V, P) operator <= (const V& lhs, const value::abstract::proxy<P>& rhs); + // Op >=. + template <typename P, typename V> + xtd_op_geq_trait(P, V) operator >= (const value::abstract::proxy<P>& lhs, const V& rhs); + template <typename V, typename P> + xtd_op_geq_trait(V, P) operator >= (const V& lhs, const value::abstract::proxy<P>& rhs); + // Op >. + template <typename P, typename V> + xtd_op_greater_trait(P, V) operator > (const value::abstract::proxy<P>& lhs, const V& rhs); + template <typename V, typename P> + xtd_op_greater_trait(V, P) operator > (const V& lhs, const value::abstract::proxy<P>& rhs); + + // Op and. + template <typename P, typename V> + xtd_op_land_trait(P, V) operator and (const value::abstract::proxy<P>& lhs, const V& rhs); + template <typename V, typename P> + xtd_op_land_trait(V, P) operator and (const V& lhs, const value::abstract::proxy<P>& rhs); + // Op or. + template <typename P, typename V> + xtd_op_lor_trait(P, V) operator or (const value::abstract::proxy<P>& lhs, const V& rhs); + template <typename V, typename P> + xtd_op_lor_trait(V, P) operator or (const V& lhs, const value::abstract::proxy<P>& rhs); + // Op xor. + template <typename P, typename V> + xtd_op_lxor_trait(P, V) operator xor (const value::abstract::proxy<P>& lhs, const V& rhs); + template <typename V, typename P> + xtd_op_lxor_trait(V, P) operator xor (const V& lhs, const value::abstract::proxy<P>& rhs); + + // FIXME: To be continued. + + + +# ifndef OLN_INCLUDE_ONLY + + + // Unary ops. + //--------------------------- + + + // Op -. + template <typename P> + xtd_op_uminus_trait(P) operator - (const value::abstract::proxy<P>& val) + { + return - val.exact().value(); + } + + // Op not. + + template <typename P> + xtd_op_lnot_trait(P) + operator not (const value::abstract::proxy<P>& val) + { + return not val.exact().value(); + } + + + // FIXME: To be continued. + + + + // Binary ops. + //--------------------------- + + // Op +. + + template <typename P, typename V> + xtd_op_plus_trait(P, V) + operator + (const value::abstract::proxy<P>& lhs, const V& rhs) + { + return lhs.exact().value() + rhs; + } + + template <typename V, typename P> + xtd_op_plus_trait(V, P) + operator + (const V& lhs, const value::abstract::proxy<P>& rhs) + { + return lhs + rhs.exact().value(); + } + + // Op -. + + template <typename P, typename V> + xtd_op_minus_trait(P, V) + operator - (const value::abstract::proxy<P>& lhs, const V& rhs) + { + return lhs.exact().value() - rhs; + } + + template <typename V, typename P> + xtd_op_minus_trait(V, P) + operator - (const V& lhs, const value::abstract::proxy<P>& rhs) + { + return lhs - rhs.exact().value(); + } + + // Op *. + + template <typename P, typename V> + xtd_op_mult_trait(P, V) + operator * (const value::abstract::proxy<P>& lhs, const V& rhs) + { + return lhs.exact().value() * rhs; + } + + template <typename V, typename P> + xtd_op_mult_trait(V, P) + operator * (const V& lhs, const value::abstract::proxy<P>& rhs) + { + return lhs * rhs.exact().value(); + } + + // Op /. + + template <typename P, typename V> + xtd_op_div_trait(P, V) + operator / (const value::abstract::proxy<P>& lhs, const V& rhs) + { + return lhs.exact().value() / rhs; + } + + template <typename V, typename P> + xtd_op_div_trait(V, P) + operator / (const V& lhs, const value::abstract::proxy<P>& rhs) + { + return lhs / rhs.exact().value(); + } + + // Op %. + + template <typename P, typename V> + xtd_op_mod_trait(P, V) + operator % (const value::abstract::proxy<P>& lhs, const V& rhs) + { + return lhs.exact().value() % rhs; + } + + template <typename V, typename P> + xtd_op_mod_trait(V, P) + operator % (const V& lhs, const value::abstract::proxy<P>& rhs) + { + return lhs % rhs.exact().value(); + } + + + // Op ==. + + template <typename P, typename V> + xtd_op_eq_trait(P, V) + operator == (const value::abstract::proxy<P>& lhs, const V& rhs) + { + return lhs.exact().value() == rhs; + } + + template <typename V, typename P> + xtd_op_eq_trait(V, P) + operator == (const V& lhs, const value::abstract::proxy<P>& rhs) + { + return lhs == rhs.exact().value(); + } + + + // Op !=. + + template <typename P, typename V> + xtd_op_neq_trait(P, V) + operator != (const value::abstract::proxy<P>& lhs, const V& rhs) + { + return lhs.exact().value() != rhs; + } + + template <typename V, typename P> + xtd_op_neq_trait(V, P) + operator != (const V& lhs, const value::abstract::proxy<P>& rhs) + { + return lhs != rhs.exact().value(); + } + + + // Op <. + + template <typename P, typename V> + xtd_op_less_trait(P, V) + operator < (const value::abstract::proxy<P>& lhs, const V& rhs) + { + return lhs.exact().value() < rhs; + } + + template <typename V, typename P> + xtd_op_less_trait(V, P) + operator < (const V& lhs, const value::abstract::proxy<P>& rhs) + { + return lhs < rhs.exact().value(); + } + + // Op <=. + + template <typename P, typename V> + xtd_op_leq_trait(P, V) + operator <= (const value::abstract::proxy<P>& lhs, const V& rhs) + { + return lhs.exact().value() <= rhs; + } + + template <typename V, typename P> + xtd_op_leq_trait(V, P) + operator <= (const V& lhs, const value::abstract::proxy<P>& rhs) + { + return lhs <= rhs.exact().value(); + } + + // Op >=. + + template <typename P, typename V> + xtd_op_geq_trait(P, V) + operator >= (const value::abstract::proxy<P>& lhs, const V& rhs) + { + return lhs.exact().value() >= rhs; + } + + template <typename V, typename P> + xtd_op_geq_trait(V, P) + operator >= (const V& lhs, const value::abstract::proxy<P>& rhs) + { + return lhs >= rhs.exact().value(); + } + + // Op >. + + template <typename P, typename V> + xtd_op_greater_trait(P, V) + operator > (const value::abstract::proxy<P>& lhs, const V& rhs) + { + return lhs.exact().value() > rhs; + } + + template <typename V, typename P> + xtd_op_greater_trait(V, P) + operator > (const V& lhs, const value::abstract::proxy<P>& rhs) + { + return lhs > rhs.exact().value(); + } + + + // Op and. + + template <typename P, typename V> + xtd_op_land_trait(P, V) + operator and (const value::abstract::proxy<P>& lhs, const V& rhs) + { + return lhs.exact().value() and rhs; + } + + template <typename V, typename P> + xtd_op_land_trait(V, P) + operator and (const V& lhs, const value::abstract::proxy<P>& rhs) + { + return lhs and rhs.exact().value(); + } + + // Op or. + + template <typename P, typename V> + xtd_op_lor_trait(P, V) + operator or (const value::abstract::proxy<P>& lhs, const V& rhs) + { + return lhs.exact().value() or rhs; + } + + template <typename V, typename P> + xtd_op_lor_trait(V, P) + operator or (const V& lhs, const value::abstract::proxy<P>& rhs) + { + return lhs or rhs.exact().value(); + } + + // Op xor. + + template <typename P, typename V> + xtd_op_lxor_trait(P, V) + operator xor (const value::abstract::proxy<P>& lhs, const V& rhs) + { + return lhs.exact().value() xor rhs; + } + + template <typename V, typename P> + xtd_op_lxor_trait(V, P) + operator xor (const V& lhs, const value::abstract::proxy<P>& rhs) + { + return lhs xor rhs.exact().value(); + } + + // FIXME: To be continued. + +# endif + +} // end of namespace oln + + +#endif // ! OLN_CORE_VALUE_PROXY_HH Index: oln/value/rw_counter.hh =================================================================== --- oln/value/rw_counter.hh (revision 0) +++ oln/value/rw_counter.hh (revision 0) @@ -0,0 +1,241 @@ +// Copyright (C) 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 OLN_CORE_VALUE_RW_COUNTER_HH +# define OLN_CORE_VALUE_RW_COUNTER_HH + +# include <iostream> +# include <map> +# include <oln/value/proxy.hh> +# include <oln/core/abstract/image/all.hh> + + +namespace oln +{ + + + namespace value + { + + + struct counter + { + typedef std::map<void*, unsigned> map_t; + + // read-write call + static unsigned& n_readwrite_calls(const oln::type& ima) + { + static map_t n; + return n[(void*)(&ima)]; + } + // read-only call + static unsigned& n_readonly_calls(const oln::type& ima) + { + static map_t n; + return n[(void*)(&ima)]; + } + // read (effective) + static unsigned& n_reads(const oln::type& ima) + { + static map_t n; + return n[(void*)(&ima)]; + } + // write (effective) + static unsigned& n_writes(const oln::type& ima) + { + static map_t n; + return n[(void*)(&ima)]; + } + + static void print(const oln::type& ima) + { + std::cout << "n_readwrite_calls = " << n_readwrite_calls(ima) << std::endl + << "n_readonly_calls = " << n_readonly_calls(ima) << std::endl + << "n_reads = " << n_reads(ima) << std::endl + << "n_writes = " << n_writes(ima) << std::endl; + } + }; + + + template <typename I> + class rw_counter : public abstract::proxy< rw_counter<I> > + { + public: + + typedef oln_value(I) value_type; + + // Ctor. + rw_counter(oln::abstract::mutable_image<I>& ima, + const oln_psite(I)& p); + + // Read. + template <typename V> + operator V() const; + + // Explicit read. + oln_rvalue(I) value() const; + + // Write. + template <typename V> + rw_counter<I>& operator=(const V& value); + + protected: + I& ima_; + const oln_psite(I)& p_; + }; + + + template <typename I> + std::ostream& operator<<(std::ostream& ostr, const rw_counter<I>& proxy); + + + template <typename I> + class ro_counter : public abstract::proxy< ro_counter<I> > + { + public: + + typedef oln_value(I) value_type; + + // Ctor. + ro_counter(const oln::abstract::image<I>& ima, + const oln_psite(I)& p); + + // Read. + template <typename V> + operator V() const; + + // Explicit read. + oln_rvalue(I) value() const; + + protected: + const I& ima_; + const oln_psite(I)& p_; + }; + + + template <typename I> + std::ostream& operator<<(std::ostream& ostr, const ro_counter<I>& proxy); + + + +# ifndef OLN_INCLUDE_ONLY + + // Ctor. + template <typename I> + rw_counter<I>::rw_counter(oln::abstract::mutable_image<I>& ima, + const oln_psite(I)& p) + : ima_(ima.exact()), + p_(p) + { + ++counter::n_readwrite_calls(ima_); + } + + // Read. + template <typename I> + template <typename V> + rw_counter<I>::operator V() const + { + ++counter::n_reads(ima_); + V tmp = ima_(p_); + return tmp; + } + + // Explicit read. + template <typename I> + oln_rvalue(I) + rw_counter<I>::value() const + { + ++counter::n_reads(ima_); + return ima_(p_); + } + + // Write. + + template <typename I> + template <typename V> + rw_counter<I>& + rw_counter<I>::operator=(const V& value) + { + ima_(p_) = value; + ++counter::n_writes(ima_); + return *this; + } + + // Op <<. + template <typename I> + std::ostream& operator<<(std::ostream& ostr, + const rw_counter<I>& proxy) + { + return ostr << proxy.value(); + } + + + // Ctor. + template <typename I> + ro_counter<I>::ro_counter(const oln::abstract::image<I>& ima, + const oln_psite(I)& p) + : ima_(ima.exact()), + p_(p) + { + ++counter::n_readonly_calls(ima_); + } + + // Read. + template <typename I> + template <typename V> + ro_counter<I>::operator V() const + { + ++counter::n_reads(ima_); + V tmp = ima_(p_); + return tmp; + } + + // Explicit read. + template <typename I> + oln_rvalue(I) + ro_counter<I>::value() const + { + ++counter::n_reads(ima_); + return ima_(p_); + } + + // Op <<. + template <typename I> + std::ostream& operator<<(std::ostream& ostr, + const ro_counter<I>& proxy) + { + return ostr << proxy.value(); + } + +# endif + + } // end of namespace oln::value + +} // end of namespace oln + + +#endif // ! OLN_CORE_VALUE_RW_COUNTER_HH
participants (1)
-
Thierry GERAUD