2005-02-08 Thierry GERAUD theo@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