2005-02-08 Thierry GERAUD <theo(a)tegucigalpa.lrde.epita.fr>
* oln/core/value_box.hh: Unbox image attribute.
* oln/core/abstract/image_with_data.hh: Clean up in ctors.
* oln/core/abstract/data_storage.hh: Fix bug in size().
* oln/core/2d/array2d.hh: Fix name of size impl.
Index: olena/oln/core/value_box.hh
===================================================================
--- olena/oln/core/value_box.hh (revision 29)
+++ olena/oln/core/value_box.hh (working copy)
@@ -30,10 +30,6 @@
# include <ostream>
-// for mlc::box<T>:
-
-# include <mlc/box.hh>
-
# include <oln/core/macros.hh>
// the proper macro:
@@ -91,7 +87,7 @@
template <typename V>
value_box& operator=(const V& value)
{
- ima_->set(p_, value);
+ ima_.set(p_, value);
return *this;
}
@@ -107,7 +103,7 @@
template <typename II>
value_box& operator=(const value_box<II>& rhs)
{
- ima_->set(p_, rhs); // automatic conversion from rhs to oln_value_type(I)
+ ima_.set(p_, rhs); // automatic conversion from rhs to oln_value_type(I)
return *this;
}
@@ -122,7 +118,7 @@
template <typename A, typename V>
value_box& set(void (I::*method)(A), const V& value)
{
- ima_->set(p_, method, value);
+ ima_.set(p_, method, value);
return *this;
}
@@ -137,13 +133,13 @@
template <typename V>
operator const V() const
{
- const V value = ima_->get(p_);
+ const V value = ima_.get(p_);
return value;
}
operator const oln_value_type(I)() const
{
- return ima_->get(p_);
+ return ima_.get(p_);
}
@@ -160,7 +156,7 @@
const oln_value_type(I) value() const
{
- return ima_->get(p_);
+ return ima_.get(p_);
}
@@ -174,8 +170,8 @@
/// Ctor (restricted access).
- value_box(I& ima, const oln_point_type(I)& p) :
- ima_(ima),
+ value_box(abstract::image<I>& ima, const oln_point_type(I)& p) :
+ ima_(ima.exact()),
p_(p)
{
}
@@ -192,7 +188,7 @@
! attributes !
*------------*/
- mlc::box<I> ima_;
+ I& ima_;
oln_point_type(I) p_;
};
@@ -216,10 +212,9 @@
public:
+ /*! \brief Assignment (op=) is declared but undefined.
+ */
- // FIXME: no operator= was provided here so 'self = self' was possible...
- // FIXME: below, a single decl has been added; to be tested...
-
template <typename V>
void operator=(const V&) const;
@@ -232,13 +227,13 @@
template <typename V>
operator const V() const
{
- const V value = ima_->get(p_);
+ const V value = ima_.get(p_);
return value;
}
operator const oln_value_type(I)() const
{
- return ima_->get(p_);
+ return ima_.get(p_);
}
@@ -255,7 +250,7 @@
const oln_value_type(I) value() const
{
- return ima_->get(p_);
+ return ima_.get(p_);
}
// IDEA: provide op->
@@ -270,8 +265,8 @@
/// Ctor (restricted access).
- value_box(const I& ima, const oln_point_type(I)& p) :
- ima_(ima),
+ value_box(const abstract::image<I>& ima, const oln_point_type(I)& p) :
+ ima_(ima.exact()),
p_(p)
{
}
@@ -288,7 +283,7 @@
! attributes !
*------------*/
- mlc::box<const I> ima_;
+ const I& ima_;
oln_point_type(I) p_;
};
Index: olena/oln/core/abstract/image_with_data.hh
===================================================================
--- olena/oln/core/abstract/image_with_data.hh (revision 29)
+++ olena/oln/core/abstract/image_with_data.hh (working copy)
@@ -137,18 +137,18 @@
/*! \brief Constructor (protected) with no memory allocation for
** data.
*/
- image_with_data()
+ image_with_data() :
+ data_(0)
{
- data_ = 0;
}
/*! \brief Constructor (protected) with memory allocation for
** data.
*/
- image_with_data(const oln_size_type(E)& size)
+ image_with_data(const oln_size_type(E)& size) :
+ data_(new oln_value_container_type(E)(size))
{
- data_ = new oln_value_container_type(E)(size);
}
Index: olena/oln/core/abstract/data_storage.hh
===================================================================
--- olena/oln/core/abstract/data_storage.hh (revision 29)
+++ olena/oln/core/abstract/data_storage.hh (working copy)
@@ -54,7 +54,7 @@
const oln_size_type(E)& size() const
{
- return this->exact().impl_size(this->s);
+ return this->exact().impl_size();
}
void resize(const oln_size_type(E)& s)
Index: olena/oln/core/2d/array2d.hh
===================================================================
--- olena/oln/core/2d/array2d.hh (revision 29)
+++ olena/oln/core/2d/array2d.hh (working copy)
@@ -108,7 +108,7 @@
invariant_();
}
- const size2d& size() const
+ const size2d& impl_size() const
{
return size_;
}
Index: metalic/mlc/tracked_ptr.hh
===================================================================
--- metalic/mlc/tracked_ptr.hh (revision 29)
+++ metalic/mlc/tracked_ptr.hh (working copy)
@@ -28,10 +28,11 @@
#ifndef METALIC_TRACKED_PTR_HH
# define METALIC_TRACKED_PTR_HH
-# include <ostream>
+# include <iostream>
# include <set>
# include <map>
+# include <mlc/contract.hh>
namespace mlc {
@@ -42,93 +43,148 @@
namespace internal {
+ /*! \class tracked_ptr_proxy<T>
+ **
+ ** Class that effectively holds a pointer. For use in class
+ ** tracked_ptr.
+ **
+ ** Parameter T is the type of pointed data.
+ */
+
template <class T>
- class tracked_ptr_proxy
+ struct /* HERE: class */ tracked_ptr_proxy
{
friend class tracked_ptr<T>;
- // attributes
+ /// Attributes.
+
T* ptr_;
std::set<const tracked_ptr<T>*> holders_;
- // w/o impl
+ /// Cpy ctor is not impled.
tracked_ptr_proxy(const tracked_ptr_proxy&);
+
+ /// Assignmt op is not impled.
void operator=(const tracked_ptr_proxy&);
- // methods
- tracked_ptr_proxy() :
- ptr_(0)
- {
- }
-
+ /*! \brief Ctor.
+ **
+ ** We have a new proxy so we have to make sure that the pointer,
+ ** if not null, was not already proxified, meaning that this new
+ ** proxy handles 'new' data.
+ */
tracked_ptr_proxy(T* ptr) :
- ptr_(0)
+ ptr_(0),
+ holders_()
{
- set_ptr(ptr);
+ if (ptr != 0)
+ {
+ invariant(proxy_of()[ptr] == 0);
+ this->ptr_ = ptr;
+ proxy_of()[this->ptr_] = this;
+ }
+ else
+ this->ptr_ = 0;
}
- void set_ptr(T* new_ptr)
+
+ /*! \brief Change data pointer.
+ **
+ ** If the change is effective, former data are deleted.
+ */
+ void set_ptr(T* ptr)
{
- if (new_ptr == this->ptr_)
- return;
- T* old_ptr = this->ptr_;
- if (old_ptr != 0)
+ if (ptr == this->ptr_)
{
- assert(proxy_of()[old_ptr] == this);
- proxy_of().erase(old_ptr);
+ // nothing to be done
+ return;
+ }
+
+ if (this->ptr_ != 0)
+ {
+ invariant(proxy_of()[this->ptr_] == this);
+ proxy_of().erase(this->ptr_);
+ delete this->ptr_;
+ this->ptr_ = 0; // safety
};
- this->ptr_ = new_ptr;
- if (new_ptr != 0)
+
+ // same code as ctor:
+ if (ptr != 0)
{
- assert(proxy_of()[new_ptr] == 0);
- proxy_of()[new_ptr] = this;
- };
+ invariant(proxy_of()[ptr] == 0);
+ this->ptr_ = ptr;
+ proxy_of()[this->ptr_] = this;
+ }
+ else
+ this->ptr_ = 0;
}
+
+ /*! \brief Register a new holder.
+ **
+ ** \precondition Test that it is effectively a new holder.
+ */
void register_holder(const tracked_ptr<T>* holder)
{
- assert(holder != 0);
- assert(holders_.find(holder) == holders_.end());
+ precondition(holder != 0);
+ precondition(holders_.find(holder) == holders_.end());
holders_.insert(holder);
}
+
+ /*! \brief Unregister a holder.
+ **
+ ** If it is the last holder and if data is not null, data are
+ ** deleted. In that case, the return value (true) allows the
+ ** tracked_pointer to know that the proxy has to be deleted.
+ **
+ ** \precondition Test that it is effectively a holder.
+ ** \return True if data is deleted, false otherwise
+ */
+
bool unregister_holder(const tracked_ptr<T>* holder)
{
- assert(holder != 0);
- assert(holders_.size() > 0);
+ // "simple" tests:
+ precondition(holder != 0);
+ precondition(holders_.size() > 0);
- typename std::set<const tracked_ptr<T>*>::iterator e =
holders_.find(holder);
- assert(e != holders_.end());
- holders_.erase(e);
+ // "main" test:
+ // note that the couple of "simple" tests above are subtests of the following
one
+ typename std::set<const tracked_ptr<T>*>::iterator h =
holders_.find(holder);
+ precondition(h != holders_.end());
- if (holders_.size() == 0)
+ holders_.erase(h);
+
+ if (holders_.size() == 0 && this->ptr_ != 0)
{
- proxy_of()[ptr_] = 0;
- delete ptr_;
- ptr_ = 0;
+ proxy_of()[this->ptr_] = 0;
+ delete this->ptr_;
+ this->ptr_ = 0; // safety
return true;
}
+
return false;
}
+
// procedures
typedef std::map<const T*, const tracked_ptr_proxy*> map_type;
static map_type& proxy_of()
{
- static map_type proxy_of_;
- return proxy_of_;
+ static map_type* proxy_of_ = new map_type;
+ return *proxy_of_;
}
friend
std::ostream& operator<<(std::ostream& ostr, const
tracked_ptr_proxy& proxy)
{
- ostr << "[ptr=" << proxy.ptr_ << " holders=(";
+ ostr << "proxy " << &proxy << " [ptr="
<< proxy.ptr_ << " holders=(";
typename std::set<const tracked_ptr<T>*>::const_iterator i =
proxy.holders_.begin();
bool ok = i != proxy.holders_.end();
while (ok)
@@ -143,7 +199,7 @@
};
- } // end of namspace internal
+ } // end of namespace internal
@@ -154,155 +210,185 @@
{
public:
+ /*! \brief Mimics the behavior of op* for a pointer in the const case.
+ **
+ ** \invariant Pointer proxy exists.
+ ** \precondition Data exists (is not null).
+ */
const T& operator*() const
{
- assert(proxy_ != 0 and proxy_->ptr_ != 0);
+ invariant(proxy_ != 0);
+ precondition(proxy_->ptr_ != 0);
return *(proxy_->ptr_);
}
+ /*! \brief Mimics the behavior of op* for a pointer in the mutable case.
+ **
+ ** \invariant Pointer proxy exists.
+ ** \precondition Data exists (is not null).
+ */
T& operator*()
{
- assert(proxy_ != 0 and proxy_->ptr_ != 0);
+ invariant(proxy_ != 0);
+ precondition(proxy_->ptr_ != 0);
return *(proxy_->ptr_);
}
+ /*! \brief Mimics the behavior of op-> for a pointer in the const case.
+ **
+ ** \invariant Pointer proxy exists.
+ */
const T*const operator->() const
{
- assert(proxy_ != 0);
+ invariant(proxy_ != 0);
return proxy_->ptr_;
}
+ /*! \brief Mimics the behavior of op-> for a pointer in the mutable case.
+ **
+ ** \invariant Pointer proxy exists.
+ */
T*const operator->()
{
- assert(proxy_ != 0);
+ invariant(proxy_ != 0);
return proxy_->ptr_;
}
+ /// Coercion towards Boolean (for arithmetical tests).
operator bool() const
{
- return proxy_ != 0 and proxy_->ptr_ != 0;
+ invariant(proxy_ != 0);
+ return proxy_->ptr_ != 0;
}
- bool operator not() const
+ /// Negation (for arithmetical tests).
+ bool operator !() const
{
- return not bool(*this);
+ invariant(proxy_ != 0);
+ return ! bool(*this);
}
+ /// Comparison 'equal to' (for arithmetical tests).
bool operator==(int b) const
{
+ invariant(proxy_ != 0);
return bool(*this) == bool(b);
}
+ /// Comparison 'not equal to' (for arithmetical tests).
bool operator!=(int b) const
{
+ invariant(proxy_ != 0);
return bool(*this) != bool(b);
}
- // hook:
- const internal::tracked_ptr_proxy<T>* proxy() const { return proxy_; }
+ /// Hook that gives access to the data proxy.
+ const internal::tracked_ptr_proxy<T>* proxy() const { return this->proxy_;
}
+ internal::tracked_ptr_proxy<T>* proxy() { return this->proxy_;
}
- // ctors
- tracked_ptr() :
- proxy_(0)
- {
- invariant_();
- }
-
- tracked_ptr(T* ptr) :
+ /*! \brief Ctor.
+ **
+ ** Creates a proxy that knows the target data pointer. This
+ ** pointer can be null (0).
+ */
+ tracked_ptr(T* ptr = 0) :
proxy_(new internal::tracked_ptr_proxy<T>(ptr))
{
- proxy_->register_holder(this);
+ this->proxy_->register_holder(this);
invariant_();
}
- // shallow copy
+ /*! \brief Cpy ctor performs a shallow copy.
+ **
+ ** The data proxy of \a rhs is shared with the constructed
+ ** tracked_ptr.
+ */
tracked_ptr(const tracked_ptr& rhs) :
proxy_(rhs.proxy_)
{
- if (proxy_ != 0)
- proxy_->register_holder(this);
+ precondition(rhs.proxy_ != 0);
+ this->proxy_->register_holder(this);
invariant_();
}
- // assignment
+ /*! \brief Assignment operator with rhs being a tracked pointer.
+ **
+ ** The lhs proxy unregisters its data and registers the rhs data.
+ ** In the case of both pointers have the same value, no action is
+ ** performed and a warning is produced. The unregistration
+ ** process may desallocate data if the target pointer was the only
+ ** access to those data.
+ */
tracked_ptr& operator=(const tracked_ptr& rhs)
{
- invariant_();
- if (rhs == 0)
- return *this;
+ invariant(this->proxy_ != 0);
+ precondition(rhs.proxy_ != 0);
+
+ invariant_(); // safety
+
if (rhs.proxy_ == this->proxy_)
- return *this;
- if (this->release_proxy_())
- delete this->proxy_;
+ {
+ std::cerr << "warning: nothing done cause both objects share the same
data!" << std::endl;
+ // FIXME: say more
+ // e.g.: ima1 = ima2; ima2 = ima1;
+ return *this;
+ }
+
+ if (this->proxy_->unregister_holder(this))
+ {
+ // the current 'tracked pointer' was the only access to
+ // some data (this->proxy_->ptr_); data has been
+ // desallocated, so it goes the same for the proxy:
+ delete this->proxy_;
+ }
+
this->proxy_ = rhs.proxy_;
this->proxy_->register_holder(this);
+
invariant_();
return *this;
}
+
+ /*! \brief Assignment operator with rhs being a data pointer.
+ **
+ ** This assignment just changes the pointed data.
+ */
tracked_ptr& operator=(T* ptr)
{
- if (proxy_ != 0)
- {
- assert(proxy_->holders_.size() <= 1);
- this->release_proxy_();
- }
- else
- proxy_ = new internal::tracked_ptr_proxy<T>(ptr);
- this->proxy_->register_holder(this);
+ invariant(this->proxy_ != 0);
+ this->proxy_->set_ptr(ptr);
return *this;
}
- // dtor
+ // Dtor.
+
~tracked_ptr()
{
- invariant_();
- if (release_proxy_())
- delete proxy_;
- proxy_ = 0;
- }
-
- // dangerous! (?)
-
- void reset_()
- {
- invariant_();
- if (proxy_ == 0 or proxy_->ptr_ == 0)
- return;
- T* ptr = proxy_->ptr_;
- std::set<const tracked_ptr<T>*>& holders = proxy_->holders_;
- typename std::set<const tracked_ptr<T>*>::iterator i;
- for (i = holders.begin(); i != holders.end(); ++i)
+ invariant(this->proxy_ != 0);
+ if (this->proxy_->unregister_holder(this))
{
- if (*i == this)
- continue;
- tracked_ptr<T>* holder = const_cast<tracked_ptr<T>*>(*i);
- holder->proxy_ = 0;
+ // the current 'tracked pointer' was the only access to
+ // some data (this->proxy_->ptr_); data has been
+ // desallocated, so it goes the same for the proxy:
+ delete this->proxy_;
}
- delete this->proxy_->ptr_;
- delete this->proxy_;
- this->proxy_ = 0;
+ this->proxy_ = 0; // safety
}
private:
+ /// Only attribute.
+
internal::tracked_ptr_proxy<T>* proxy_;
- bool release_proxy_()
- {
- invariant_();
- if (proxy_ == 0)
- return false;
- return proxy_->unregister_holder(this);
- }
-
void invariant_() const
{
if (proxy_ == 0)
@@ -313,9 +399,15 @@
assert((*i)->proxy_ == this->proxy_);
}
+ friend
+ std::ostream& operator<<(std::ostream& ostr, const tracked_ptr&
ptr)
+ {
+ invariant(ptr.proxy_ != 0);
+ return ostr << "tracked_ptr " << &ptr << "
--> " << *(ptr.proxy_);
+ }
};
+
-
} // end of namespace mlc
Index: metalic/mlc/any.hh
===================================================================
--- metalic/mlc/any.hh (revision 29)
+++ metalic/mlc/any.hh (working copy)
@@ -32,7 +32,7 @@
-// abrev
+// abbrev
#define any_mem(E) any <E, dispatch_policy::best_memory>
@@ -46,14 +46,13 @@
{
struct best_speed;
struct best_memory;
- struct compromise;
+ struct simple;
};
// any
- template <typename E,
- typename Dispatch_Policy = dispatch_policy::best_memory>
+ template <typename E, typename Dispatch_Policy = dispatch_policy::simple>
struct any;
@@ -71,12 +70,34 @@
precondition(exact_ptr != 0);
return *exact_ptr;
}
+
+ /// Assignment (op=).
+
+ any& operator=(const any& rhs)
+ {
+ // do nothing
+ // so that "this->exact_ptr" is unchanged
+ return *this;
+ }
+
+ /// Copy Ctor.
+
+ any(const any& rhs) :
+ exact_ptr(0) // safety
+ {
+ // this->exact_ptr is *not* copied
+ // its value has to be set in subclasses copy ctors.
+ }
+
protected:
any(E* exact_ptr) : exact_ptr(exact_ptr) {}
virtual ~any() {}
+
+ /// Only attribute.
E* exact_ptr;
};
+
template <typename E>
struct any__best_speed : public any<E, dispatch_policy::best_speed>
{
@@ -104,8 +125,8 @@
protected:
any() {}
- any(E* exact_ptr); // safety: w/o impl
- virtual ~any() {}
+ any(E* exact_ptr_does_not_exist_in_this_version); // safety
+ virtual ~any() {} // FIXME: virtual for a "best memory" version!?
};
template <typename E>
@@ -123,11 +144,22 @@
- (const
char*)(void*)(&any_mem(E)::exact_obj);
- // "compromise" version of 'any'
+ // "simple" version of 'any'
template <typename E>
struct any <E,
- dispatch_policy::compromise>; // FIXME: not yet impled
+ dispatch_policy::simple>
+ {
+ E& exact() {
+ return *(E*)(void*)this;
+ }
+ const E& exact() const {
+ return *(const E*)(const void*)this;
+ }
+ protected:
+ any() {}
+ any(E* exact_ptr_does_not_exist_in_this_version); // safety
+ };
} // end of namespace mlc