BWAPI
|
00001 // Copyright (c) 2001-2007 Max-Planck-Institute Saarbruecken (Germany). 00002 // All rights reserved. 00003 // 00004 // This file is part of CGAL (www.cgal.org); you can redistribute it and/or 00005 // modify it under the terms of the GNU Lesser General Public License as 00006 // published by the Free Software Foundation; version 2.1 of the License. 00007 // See the file LICENSE.LGPL distributed with CGAL. 00008 // 00009 // Licensees holding a valid commercial license may use this file in 00010 // accordance with the commercial license agreement provided with the software. 00011 // 00012 // This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE 00013 // WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 00014 // 00015 // $URL: svn+ssh://scm.gforge.inria.fr/svn/cgal/branches/CGAL-3.5-branch/STL_Extension/include/CGAL/Handle_with_policy.h $ 00016 // $Id: Handle_with_policy.h 44351 2008-07-23 13:19:15Z hoffmann $ 00017 // 00018 // Author(s) : Michael Seel <seel@mpi-inf.mpg.de> 00019 // Arno Eigenwillig <arno@mpi-inf.mpg.de> 00020 // Lutz Kettner <kettner@mpi-inf.mpg.de> 00021 00022 #ifndef CGAL_HANDLE_WITH_POLICY_H 00023 #define CGAL_HANDLE_WITH_POLICY_H 00024 00025 #include <CGAL/basic.h> 00026 #include <CGAL/memory.h> 00027 #include <CGAL/type_traits.h> 00028 00029 #include <boost/static_assert.hpp> 00030 #include <boost/mpl/if.hpp> 00031 00032 #include <cstddef> 00033 00034 #ifdef CGAL_USE_LEDA 00035 # if CGAL_LEDA_VERSION < 500 00036 # include <LEDA/memory.h> 00037 # else 00038 # include <LEDA/system/memory.h> 00039 # endif 00040 #endif 00041 00042 00043 00044 CGAL_BEGIN_NAMESPACE 00045 00171 00172 // Forward declarations of HandlePolicy classes 00173 class Handle_policy_in_place; 00174 class Handle_policy_no_union; 00175 class Handle_policy_union; 00176 class Handle_policy_union_and_reset; 00177 00178 // Reference counted representation 00179 // ================================ 00180 00182 template <class T> 00183 class Reference_counted { 00184 public: 00185 typedef Reference_counted<T> Self; 00186 typedef T* Rep_pointer; 00187 private: 00188 mutable unsigned int count; // reference counter 00189 T rep; 00190 public: 00191 Reference_counted() : count(1) {} 00192 Reference_counted( const T& t) : count(1), rep(t) {} 00193 Reference_counted( const Self& r) : count(1), rep(r.rep) {} 00194 00195 void clear() { rep = T(); } 00196 Rep_pointer base_ptr() { return &rep; } 00197 void add_reference() { ++count; } 00198 void remove_reference() { --count; } 00199 bool is_shared() const { return count > 1; } 00200 int union_size() const { return 1+count; } 00201 void add_union_size(int) {} 00202 }; 00203 00208 template <class T> 00209 class Reference_counted_with_forwarding { 00210 public: 00211 typedef Reference_counted_with_forwarding<T> Self; 00212 typedef T* Rep_pointer; 00213 friend class Handle_policy_union; 00214 friend class Handle_policy_union_and_reset; 00215 private: 00216 mutable unsigned int count; // reference counter 00217 mutable Self* next; // forwarding pointer to valid rep or 0 00218 mutable int u_size; // union set size incl this rep and its handle 00219 mutable T rep; 00220 public: 00221 Reference_counted_with_forwarding() 00222 : count(1), next(0), u_size(2) {} 00223 Reference_counted_with_forwarding( const T& t) 00224 : count(1), next(0), u_size(2), rep(t) {} 00225 Reference_counted_with_forwarding( const Self& r) 00226 : count(1), next(0), u_size(2), rep(r.rep) {} 00227 00228 void clear() { rep = T(); } 00229 Rep_pointer base_ptr() { return &rep; } 00230 void add_reference() { ++count; } 00231 void remove_reference() { --count; } 00232 bool is_shared() const { return count > 1; } 00233 bool is_forwarding() const { return next != 0; } 00234 int union_size() const { return u_size; } 00235 void add_union_size(int a) { 00236 CGAL_precondition( u_size + a > 0); 00237 u_size += a; 00238 } 00239 }; 00240 00241 00242 struct Reference_counted_hierarchy_base {}; 00243 00244 00249 template <class Allocator_ = CGAL_ALLOCATOR(char)> 00250 class Reference_counted_hierarchy : public Reference_counted_hierarchy_base { 00251 // make sure it's always a char allocator 00252 typedef typename Allocator_::template rebind< char> Char_alloc_rebind; 00253 typedef typename Char_alloc_rebind::other Char_allocator; 00254 00255 static Char_allocator alloc; 00256 00257 public: 00258 void* operator new(size_t bytes) { return alloc.allocate( bytes); } 00259 void operator delete(void* p, size_t bytes) { 00260 alloc.deallocate((char*)p, bytes); 00261 } 00262 00263 public: 00264 typedef Allocator_ Allocator; 00265 typedef Reference_counted_hierarchy<Allocator> Self; 00266 typedef Self* Rep_pointer; 00267 private: 00268 mutable unsigned int count; // reference counter 00269 public: 00270 Reference_counted_hierarchy() : count(1) {} 00271 Reference_counted_hierarchy( const Self&) : count(1) {} 00272 00273 Rep_pointer base_ptr() { return this; } 00274 void add_reference() { ++count; } 00275 void remove_reference() { --count; } 00276 bool is_shared() const { return count > 1; } 00277 int union_size() const { return 1+count; } 00278 void add_union_size(int) {} 00279 00282 virtual Self* clone() = 0; 00284 virtual ~Reference_counted_hierarchy() {} 00291 virtual void clear() {} 00292 }; 00293 00294 template <class Alloc> 00295 typename Reference_counted_hierarchy<Alloc>::Char_allocator 00296 Reference_counted_hierarchy<Alloc>::alloc; 00297 00302 template <class Allocator_ = CGAL_ALLOCATOR(char)> 00303 class Reference_counted_hierarchy_with_union 00304 : public Reference_counted_hierarchy<Allocator_> 00305 { 00306 friend class Handle_policy_union; 00307 friend class Handle_policy_union_and_reset; 00308 public: 00309 typedef Allocator_ Allocator; 00310 typedef Reference_counted_hierarchy_with_union<Allocator> Self; 00311 private: 00312 mutable Self* next; // forwarding pointer to valid rep or 0 00313 mutable int u_size; // union set size incl this rep and its handle 00314 public: 00315 Reference_counted_hierarchy_with_union() : 00316 Reference_counted_hierarchy<Allocator_>(), next(0), u_size(2) {} 00317 bool is_forwarding() const { return next != 0; } 00318 int union_size() const { return u_size; } 00319 void add_union_size(int a) { 00320 CGAL_precondition( u_size + a > 0); 00321 u_size += a; 00322 } 00323 }; 00324 00325 00326 // Handle for reference counted representation 00327 // =========================================== 00328 00329 namespace Intern { 00330 // Some helper classes to select representation between single class 00331 // representations and class hierarchy representations. 00332 00333 // the representation type including a reference counter. 00334 // The handle allocates objects of this type. This is the version 00335 // for the single representation type. 00336 template <class T, int HandleHierarchyPolicy> 00337 struct Rep_bind_reference_counted { 00338 typedef Reference_counted<T> Rep; 00339 }; 00340 00341 // the representation type including a reference counter. 00342 // The handle allocates objects of this type. This is the version 00343 // for the class hierarchy of representation types. 00344 template <class T> 00345 struct Rep_bind_reference_counted<T, true> { 00346 typedef T Rep; 00347 }; 00348 00349 // the two versions for Reference_counted_with_forwarding 00350 template <class T, int HandleHierarchyPolicy> 00351 struct Rep_bind_reference_counted_with_forwarding { 00352 typedef Reference_counted_with_forwarding<T> Rep; 00353 }; 00354 00355 // the representation type including a reference counter. 00356 // The handle allocates objects of this type. This is the version 00357 // for the class hierarchy of representation types. 00358 template <class T> 00359 struct Rep_bind_reference_counted_with_forwarding<T, true> { 00360 Rep_bind_reference_counted_with_forwarding() { 00361 // make sure we derived from the right type 00362 typedef typename T::Allocator Alloc; 00363 typedef ::CGAL::Reference_counted_hierarchy_with_union<Alloc> 00364 Reference_counted_hierarchy_with_union; 00365 BOOST_STATIC_ASSERT(( 00366 ::CGAL::is_same_or_derived< Reference_counted_hierarchy_with_union, T >::value )); 00367 } 00368 typedef T Rep; 00369 }; 00370 00371 } 00372 00382 class Handle_policy_in_place {}; 00383 00388 class Handle_policy_no_union { 00389 public: 00393 template <class T, int hierarchy> 00394 struct Rep_bind { 00397 typedef typename 00398 Intern::Rep_bind_reference_counted<T,hierarchy>::Rep Rep; 00399 }; 00400 00410 template <class Alloc> 00411 struct Hierarchy_base { 00413 typedef Reference_counted_hierarchy<Alloc> Type; 00414 }; 00415 00422 template <class H> 00423 static void unify( const H& h, const H& g) { 00424 (void)h; // avoid warnings for unused parameters 00425 (void)g; // but keep the names in the definition for the doc. 00426 } 00427 00430 template <class H> 00431 static typename H::Rep_pointer find( const H& h) { 00432 return h.ptr_->base_ptr(); 00433 } 00434 }; 00435 00441 class Handle_policy_union { 00442 public: 00446 template <class T, int hierarchy> 00447 struct Rep_bind { 00449 Rep_bind() { 00450 //Intern::Rep_bind_reference_counted_with_forwarding<T, hierarchy> 00451 // check; 00452 // (void)check; 00453 (void)Intern::Rep_bind_reference_counted_with_forwarding<T, hierarchy>(); 00454 } 00457 typedef typename Intern::Rep_bind_reference_counted_with_forwarding<T, 00458 hierarchy>::Rep Rep; 00459 }; 00460 00470 template <class Alloc> 00471 struct Hierarchy_base { 00473 typedef Reference_counted_hierarchy_with_union<Alloc> Type; 00474 }; 00475 00484 template <class H> 00485 static void unify_large_small( const H& h, const H& g) { 00486 typename H::Rep* hrep = h.ptr_; 00487 typename H::Rep* grep = g.ptr_; 00488 CGAL_precondition( ! grep->is_forwarding()); 00489 CGAL_precondition( hrep->union_size() >= grep->union_size()); 00490 grep->add_union_size(-1); 00491 // make g point to h's rep. 00492 if ( grep->is_shared()) { 00493 // grep survises the loss of one reference 00494 // and hrep gets one more reference 00495 grep->remove_reference(); 00496 hrep->add_reference(); 00497 hrep->add_union_size( grep->union_size()); 00498 grep->next = hrep; 00499 } else { 00500 g.delete_rep( grep); // did not survive loss of handle g 00501 } 00502 // redirect handle g and incr. hrep's counter 00503 g.ptr_ = hrep; 00504 hrep->add_reference(); 00505 hrep->add_union_size(1); 00506 } 00507 00513 template <class H> 00514 static void unify( const H& h, const H& g) { 00515 if ( find(h) != find(g)) { 00516 if ( h.ptr_->union_size() > g.ptr_->union_size()) 00517 unify_large_small( h, g); // make g point to h's rep. 00518 else 00519 unify_large_small( g, h); // make h point to g's rep. 00520 } 00521 } 00522 00527 template <class H> 00528 static typename H::Rep_pointer find( const H& h) { 00529 typedef typename H::Rep Rep; 00530 if ( h.ptr_->is_forwarding()) { 00531 // find new valid representation 00532 Rep* new_rep = h.ptr_; 00533 while ( new_rep->next != 0) 00534 new_rep = static_cast<Rep*>(new_rep->next); 00535 // path compression: assign new rep to all reps seen on the path 00536 // update reference count properly: all reps on the path loose 00537 // one reference, and the new_rep gains all of them unless 00538 // the rep on the path get actually deleted. 00539 Rep* rep = h.ptr_; 00540 while ( rep != new_rep) { 00541 Rep* tmp = static_cast<Rep*>(rep->next); 00542 if ( rep->is_shared()) { 00543 // rep survives the loss of one reference 00544 // and new_rep gets one more reference 00545 rep->remove_reference(); 00546 if ( tmp != new_rep) { 00547 // re-link rep to the new_rep 00548 rep->next = new_rep; 00549 new_rep->add_reference(); 00550 } 00551 } else { 00552 h.delete_rep( rep); // we have to delete the current rep 00553 } 00554 rep = tmp; 00555 } 00556 // hook h to new_rep 00557 h.ptr_ = new_rep; 00558 new_rep->add_reference(); 00559 } 00560 return h.ptr_->base_ptr(); 00561 } 00562 }; 00563 00573 class Handle_policy_union_and_reset { 00574 public: 00578 template <class T, int hierarchy> 00579 struct Rep_bind { 00581 Rep_bind() { 00582 //Intern::Rep_bind_reference_counted_with_forwarding<T, hierarchy> 00583 // check; 00584 // (void)check; 00585 (void)Intern::Rep_bind_reference_counted_with_forwarding<T, hierarchy>(); 00586 } 00589 typedef typename Intern::Rep_bind_reference_counted_with_forwarding<T, 00590 hierarchy>::Rep Rep; 00591 }; 00592 00602 template <class Alloc> 00603 struct Hierarchy_base { 00605 typedef Reference_counted_hierarchy_with_union<Alloc> Type; 00606 }; 00607 00608 // abbreviation to re-use its implementation below. 00609 typedef Handle_policy_union U; 00610 00618 template <class H> 00619 static void unify( const H& h, const H& g) { 00620 if ( find(h) != find(g)) { 00621 if ( h.ptr_->union_size() > g.ptr_->union_size()) { 00622 // reset representation in g to default construction of T 00623 if ( g.ptr_->is_shared()) 00624 g.ptr_->clear(); 00625 U::unify_large_small( h, g); // make g point to h's rep. 00626 } else { 00627 // reset representation in h to default construction of T 00628 if ( h.ptr_->is_shared()) 00629 h.ptr_->clear(); 00630 U::unify_large_small( g, h); // make h point to g's rep. 00631 } 00632 } 00633 } 00634 00639 template <class H> 00640 static typename H::Rep_pointer find( const H& h) { return U::find(h); } 00641 }; 00642 00643 00710 template <class T, 00711 class HandlePolicy = Handle_policy_no_union, 00712 class Allocator_ = CGAL_ALLOCATOR(T)> 00713 class Handle_with_policy { 00714 public: 00716 typedef Handle_with_policy< T, HandlePolicy, Allocator_> Self; 00717 00719 typedef HandlePolicy Handle_policy; 00720 00722 typedef Allocator_ Allocator; 00723 00724 enum { is_class_hierarchy = 00725 ::CGAL::is_same_or_derived< Reference_counted_hierarchy_base, T>::value }; 00726 typedef typename Handle_policy::template Rep_bind< T, is_class_hierarchy > Bind; 00727 // instantiate Rep_bind to activate compile time check in there 00728 static Bind bind; 00729 // Define type that is used for function matching 00730 typedef typename ::boost::mpl::if_c< 00731 is_class_hierarchy, 00732 ::CGAL::Tag_true, 00733 ::CGAL::Tag_false >::type 00734 Class_hierarchy; 00735 00739 typedef typename Bind::Rep Rep; 00740 00741 typedef typename Rep::Rep_pointer Rep_pointer; 00742 00743 typedef typename Allocator_::template rebind<Rep>::other Rep_allocator; 00744 00745 00747 typedef std::ptrdiff_t Id_type; 00748 00749 friend class Handle_policy_no_union; 00750 friend class Handle_policy_union; 00751 friend class Handle_policy_union_and_reset; 00752 private: 00753 mutable Rep* ptr_; 00754 00755 // We have to distinguish between allocating single representations 00756 // and where we have a class hierarchy of representations, where the 00757 // user is responsible for allocating the first representations 00758 // and we can just \c clone and delete them. 00759 static Rep_allocator allocator; 00760 00761 static Rep* new_rep( const Rep& rep) { 00762 BOOST_STATIC_ASSERT( !( 00763 ::CGAL::is_same_or_derived< Reference_counted_hierarchy_base, T >::value )); 00764 Rep* p = allocator.allocate(1); 00765 allocator.construct(p, rep); 00766 return p; 00767 } 00768 static void delete_rep( Rep* p, ::CGAL::Tag_false ) { 00769 allocator.destroy( p); 00770 allocator.deallocate( p, 1); 00771 } 00772 static void delete_rep( Rep* p, ::CGAL::Tag_true ) { 00773 delete p; 00774 } 00775 static void delete_rep( Rep* p) { delete_rep(p, Class_hierarchy()); } 00776 00777 static Rep* clone_rep( Rep* p, ::CGAL::Tag_false ) { 00778 return new_rep( *p); 00779 } 00780 static Rep* clone_rep( Rep* p, ::CGAL::Tag_true ) { 00781 return static_cast<Rep*>(p->clone()); 00782 } 00783 static Rep* clone_rep( Rep* p) { return clone_rep( p, Class_hierarchy()); } 00784 00785 void remove_reference() { 00786 // cleans up the possible chain of forwarding reps 00787 Handle_policy::find( *this); 00788 if ( ! is_shared()) { 00789 delete_rep( ptr_); 00790 } else { 00791 ptr_->remove_reference(); 00792 ptr_->add_union_size( -1); 00793 } 00794 } 00795 00796 template <class TT> 00797 Rep* make_from_single_arg( const TT& t, ::CGAL::Tag_false ) { 00798 return new_rep( Rep( T(t))); 00799 } 00800 template <class TT> 00801 Rep* make_from_single_arg( TT t, ::CGAL::Tag_true ) { 00802 //Bind bind_; // trigger compile-time check 00803 // (void)bind_; 00804 (void)Bind(); // shouldn't this be enough to trigger? 00805 return t; // has to be a pointer convertible to Rep* 00806 } 00807 00808 protected: 00810 T* ptr() { return static_cast<T*>(Handle_policy::find(*this));} 00812 const T* ptr() const { 00813 return static_cast<const T*>(Handle_policy::find( *this)); 00814 } 00815 00820 void unify( const Self& h) const { Handle_policy::unify( *this, h); } 00821 00826 void copy_on_write() { 00827 Handle_policy::find( *this); 00828 if ( is_shared() ) { 00829 Rep* tmp_ptr = clone_rep( ptr_); 00830 ptr_->remove_reference(); 00831 ptr_->add_union_size( -1); 00832 ptr_ = tmp_ptr; 00833 } 00834 } 00835 00837 enum Use_with_initialize_with { 00838 USE_WITH_INITIALIZE_WITH 00839 00840 }; 00841 00848 Handle_with_policy( Use_with_initialize_with) : ptr_( 0) {} 00849 00856 Handle_with_policy( Rep* p) : ptr_( p) { 00857 BOOST_STATIC_ASSERT(( 00858 ::CGAL::is_same_or_derived< Reference_counted_hierarchy_base, T >::value )); 00859 //Bind bind_; // trigger compile-time check 00860 //(void)bind_; 00861 (void)Bind(); 00862 } 00863 00870 void initialize_with( Rep* p) { 00871 BOOST_STATIC_ASSERT(( 00872 ::CGAL::is_same_or_derived< Reference_counted_hierarchy_base, T >::value )); 00873 //Bind bind_; // trigger compile-time check 00874 //(void)bind_; 00875 (void)Bind(); 00876 CGAL_precondition_msg( ptr_ == 0, "Handle_with_policy::initialize_with(): the " 00877 "representation has already been initialized."); 00878 ptr_ = p; 00879 } 00880 00887 template <class T1> 00888 void initialize_with( const T1& t1) { 00889 CGAL_precondition_msg( ptr_ == 0, "Handle_with_policy::initialize_with(): the " 00890 "representation has already been initialized."); 00891 ptr_ = make_from_single_arg( t1, Class_hierarchy()); 00892 } 00893 00896 template <class T1, class T2> 00897 void initialize_with( const T1& t1, const T2& t2) { 00898 CGAL_precondition_msg( ptr_ == 0, "Handle_with_policy::initialize_with(): the " 00899 "representation has already been initialized."); 00900 ptr_ = new_rep( Rep( T(t1,t2))); 00901 } 00902 00905 template <class T1, class T2, class T3> 00906 void initialize_with( const T1& t1, const T2& t2, const T3& t3) { 00907 CGAL_precondition_msg( ptr_ == 0, "Handle_with_policy::initialize_with(): the " 00908 "representation has already been initialized."); 00909 ptr_ = new_rep( Rep( T(t1,t2,t3))); 00910 } 00911 00914 template <class T1, class T2, class T3, class T4> 00915 void initialize_with( const T1& t1, const T2& t2, const T3& t3, 00916 const T4& t4) { 00917 CGAL_precondition_msg( ptr_ == 0, "Handle_with_policy::initialize_with(): the " 00918 "representation has already been initialized."); 00919 ptr_ = new_rep( Rep( T(t1,t2,t3,t4))); 00920 } 00921 00924 template <class T1, class T2, class T3, class T4, class T5> 00925 void initialize_with( const T1& t1, const T2& t2, const T3& t3, 00926 const T4& t4, const T5& t5) { 00927 CGAL_precondition_msg( ptr_ == 0, "Handle_with_policy::initialize_with(): the " 00928 "representation has already been initialized."); 00929 ptr_ = new_rep( Rep( T(t1,t2,t3,t4,t5))); 00930 } 00931 00934 template <class T1, class T2, class T3, class T4, class T5, class T6> 00935 void initialize_with( const T1& t1, const T2& t2, const T3& t3, 00936 const T4& t4, const T5& t5, const T6& t6) { 00937 CGAL_precondition_msg( ptr_ == 0, "Handle_with_policy::initialize_with(): the " 00938 "representation has already been initialized."); 00939 ptr_ = new_rep( Rep( T(t1,t2,t3,t4,t5,t6))); 00940 } 00941 00944 template <class T1, class T2, class T3, class T4, class T5, class T6, 00945 class T7> 00946 void initialize_with( const T1& t1, const T2& t2, const T3& t3, 00947 const T4& t4, const T5& t5, const T6& t6, 00948 const T7& t7) { 00949 CGAL_precondition_msg( ptr_ == 0, "Handle_with_policy::initialize_with(): the " 00950 "representation has already been initialized."); 00951 ptr_ = new_rep( Rep( T(t1,t2,t3,t4,t5,t6,t7))); 00952 } 00953 00956 template <class T1, class T2, class T3, class T4, class T5, class T6, 00957 class T7, class T8> 00958 void initialize_with( const T1& t1, const T2& t2, const T3& t3, 00959 const T4& t4, const T5& t5, const T6& t6, 00960 const T7& t7, const T8& t8) { 00961 CGAL_precondition_msg( ptr_ == 0, "Handle_with_policy::initialize_with(): the " 00962 "representation has already been initialized."); 00963 ptr_ = new_rep( Rep( T(t1,t2,t3,t4,t5,t6,t7,t8))); 00964 } 00965 00968 template <class T1, class T2, class T3, class T4, class T5, class T6, 00969 class T7, class T8, class T9> 00970 void initialize_with( const T1& t1, const T2& t2, const T3& t3, 00971 const T4& t4, const T5& t5, const T6& t6, 00972 const T7& t7, const T8& t8, const T9& t9) { 00973 CGAL_precondition_msg( ptr_ == 0, "Handle_with_policy::initialize_with(): the " 00974 "representation has already been initialized."); 00975 ptr_ = new_rep( Rep( T(t1,t2,t3,t4,t5,t6,t7,t8,t9))); 00976 } 00977 00978 public: 00980 Handle_with_policy() : ptr_( new_rep( Rep())) {} 00981 00983 Handle_with_policy(const Self& h) { 00984 CGAL_precondition_msg( h.ptr_ != 0, "Handle_with_policy::Handle_with_policy( Self): probably " 00985 "used special protected constructor and not the " 00986 "'initialize_with()' function."); 00987 Handle_policy::find( h); 00988 ptr_ = h.ptr_; 00989 ptr_->add_reference(); 00990 ptr_->add_union_size( 1); 00991 } 00992 00998 template <class T1> 00999 explicit Handle_with_policy( const T1& t) 01000 : ptr_( make_from_single_arg( t, Class_hierarchy())) {} 01001 01004 template <class T1, class T2> 01005 Handle_with_policy( const T1& t1, const T2& t2) : ptr_( new_rep( Rep( T( t1, t2)))) {} 01006 01009 template <class T1, class T2, class T3> 01010 Handle_with_policy( const T1& t1, const T2& t2, const T3& t3) 01011 : ptr_( new_rep( Rep( T( t1, t2, t3)))) {} 01012 01015 template <class T1, class T2, class T3, class T4> 01016 Handle_with_policy( const T1& t1, const T2& t2, const T3& t3, const T4& t4) 01017 : ptr_( new_rep( Rep( T( t1, t2, t3, t4)))) {} 01018 01021 template <class T1, class T2, class T3, class T4, class T5> 01022 Handle_with_policy( const T1& t1, const T2& t2, const T3& t3, const T4& t4, 01023 const T5& t5) 01024 : ptr_( new_rep( Rep( T( t1, t2, t3, t4, t5)))) {} 01025 01028 template <class T1, class T2, class T3, class T4, class T5, class T6> 01029 Handle_with_policy( const T1& t1, const T2& t2, const T3& t3, const T4& t4, 01030 const T5& t5, const T6& t6) 01031 : ptr_( new_rep( Rep( T( t1, t2, t3, t4, t5, t6)))) {} 01032 01035 template <class T1, class T2, class T3, class T4, class T5, class T6, 01036 class T7> 01037 Handle_with_policy( const T1& t1, const T2& t2, const T3& t3, const T4& t4, 01038 const T5& t5, const T6& t6, const T7& t7) 01039 : ptr_( new_rep( Rep( T( t1, t2, t3, t4, t5, t6, t7)))) {} 01040 01043 template <class T1, class T2, class T3, class T4, class T5, class T6, 01044 class T7, class T8> 01045 Handle_with_policy( const T1& t1, const T2& t2, const T3& t3, const T4& t4, 01046 const T5& t5, const T6& t6, const T7& t7, const T8& t8) 01047 : ptr_( new_rep( Rep( T( t1, t2, t3, t4, t5, t6, t7, t8)))) {} 01048 01051 template <class T1, class T2, class T3, class T4, class T5, class T6, 01052 class T7, class T8, class T9> 01053 Handle_with_policy( const T1& t1, const T2& t2, const T3& t3, const T4& t4, 01054 const T5& t5, const T6& t6, const T7& t7, const T8& t8, 01055 const T9& t9) 01056 : ptr_( new_rep( Rep( T( t1, t2, t3, t4, t5, t6, t7, t8, t9)))) {} 01057 01059 ~Handle_with_policy() { 01060 //Bind bind_; // trigger compile-time check 01061 //(void)bind_; 01062 (void)Bind(); 01063 CGAL_precondition_msg( ptr_ != 0, "Handle_with_policy::~Handle_with_policy(): probably used " 01064 "special protected constructor and not the " 01065 "'initialize_with()' function."); 01066 remove_reference(); 01067 } 01068 01070 Self& operator=( const Self& h) { 01071 CGAL_precondition_msg( h.ptr_ != 0, "Handle_with_policy::operator=(): probably " 01072 "used special protected constructor and not the " 01073 "'initialize_with()' function."); 01074 Handle_policy::find( h); 01075 h.ptr_->add_reference(); 01076 h.ptr_->add_union_size( 1); 01077 remove_reference(); 01078 ptr_ = h.ptr_; 01079 return *this; 01080 } 01081 01083 bool is_identical( const Self& h) const { return ptr() == h.ptr(); } 01084 01087 Id_type id() const { return reinterpret_cast<Id_type>(&*ptr()); } 01088 01091 bool is_shared() const { return ptr_->is_shared(); } 01092 01096 bool is_forwarding() const { return ptr_->is_forwarding(); } 01097 01100 int union_size() const { return ptr_->union_size(); } 01101 01102 // backwards compatible 01103 bool identical( const Self& h) const { return is_identical(h); } 01104 01105 #ifdef CGAL_HANDLE_WITH_POLICY_INTERNAL_TEST 01106 // provide access to pointer for testing only!! 01107 const Rep* test_ptr() const { return ptr_; } 01108 // provide access to pointer for testing only!! 01109 bool test_identical_ptr( const Self& h) const { return ptr_ == h.ptr_; } 01110 #endif // CGAL_HANDLE_WITH_POLICY_INTERNAL_TEST 01111 }; 01112 01113 // instantiate Rep_bind to activate compile time check in there 01114 template <class T, class Policy, class Alloc> 01115 typename Handle_with_policy<T,Policy,Alloc>::Bind Handle_with_policy<T,Policy,Alloc>::bind; 01116 01117 01119 01122 template <class T, class A> 01123 unsigned long ID_Number(const Handle_with_policy<T, Handle_policy_no_union, A>& h) 01124 { return h.id(); } 01125 01126 template <class T, class Policy, class Alloc> 01127 typename Handle_with_policy<T, Policy, Alloc>::Rep_allocator 01128 Handle_with_policy<T, Policy, Alloc>::allocator; 01129 01130 01135 template <class T, class Allocator_> 01136 class Handle_with_policy<T, Handle_policy_in_place, Allocator_> { 01137 public: 01139 typedef Handle_with_policy< T, Handle_policy_in_place, Allocator_> Self; 01140 01142 typedef Handle_policy_in_place Handle_policy; 01143 01145 typedef Allocator_ Allocator; 01146 01148 typedef T Rep; 01149 01151 typedef std::ptrdiff_t Id_type; 01152 private: 01153 // store the rep in place 01154 Rep rep; 01155 01156 protected: 01158 T* ptr() { return &rep; } 01160 const T* ptr() const { return &rep; } 01161 01163 void unify( const Self&) const {} 01164 01167 void copy_on_write() {} 01168 01170 enum Use_with_initialize_with { 01171 USE_WITH_INITIALIZE_WITH 01172 }; 01173 01177 Handle_with_policy( Use_with_initialize_with) {} 01178 01181 template <class T1> 01182 void initialize_with( const T1& t1) { rep = Rep(t1); } 01183 01186 template <class T1, class T2> 01187 void initialize_with( const T1& t1, const T2& t2) { rep = Rep(t1,t2); } 01188 01191 template <class T1, class T2, class T3> 01192 void initialize_with( const T1& t1, const T2& t2, const T3& t3) { 01193 rep = Rep(t1,t2,t3); 01194 } 01195 01198 template <class T1, class T2, class T3, class T4> 01199 void initialize_with( const T1& t1, const T2& t2, const T3& t3, 01200 const T4& t4) { 01201 rep = Rep(t1,t2,t3,t4); 01202 } 01203 01206 template <class T1, class T2, class T3, class T4, class T5> 01207 void initialize_with( const T1& t1, const T2& t2, const T3& t3, 01208 const T4& t4, const T5& t5) { 01209 rep = Rep(t1,t2,t3,t4,t5); 01210 } 01211 01214 template <class T1, class T2, class T3, class T4, class T5, class T6> 01215 void initialize_with( const T1& t1, const T2& t2, const T3& t3, 01216 const T4& t4, const T5& t5, const T6& t6) { 01217 rep = Rep(t1,t2,t3,t4,t5,t6); 01218 } 01219 01222 template <class T1, class T2, class T3, class T4, class T5, class T6, 01223 class T7> 01224 void initialize_with( const T1& t1, const T2& t2, const T3& t3, 01225 const T4& t4, const T5& t5, const T6& t6, 01226 const T7& t7) { 01227 rep = Rep(t1,t2,t3,t4,t5,t6,t7); 01228 } 01229 01232 template <class T1, class T2, class T3, class T4, class T5, class T6, 01233 class T7, class T8> 01234 void initialize_with( const T1& t1, const T2& t2, const T3& t3, 01235 const T4& t4, const T5& t5, const T6& t6, 01236 const T7& t7, const T8& t8) { 01237 rep = Rep(t1,t2,t3,t4,t5,t6,t7,t8); 01238 } 01239 01242 template <class T1, class T2, class T3, class T4, class T5, class T6, 01243 class T7, class T8, class T9> 01244 void initialize_with( const T1& t1, const T2& t2, const T3& t3, 01245 const T4& t4, const T5& t5, const T6& t6, 01246 const T7& t7, const T8& t8, const T9& t9) { 01247 rep = Rep(t1,t2,t3,t4,t5,t6,t7,t8,t9); 01248 } 01249 01250 public: 01252 Handle_with_policy() {} 01253 01255 Handle_with_policy(const Self& h) : rep( h.rep) {} 01256 01259 template <class T1> 01260 explicit Handle_with_policy( const T1& t) : rep( Rep(t)) {} 01261 01264 template <class T1, class T2> 01265 Handle_with_policy( const T1& t1, const T2& t2) : rep( Rep(t1,t2)) {} 01266 01269 template <class T1, class T2, class T3> 01270 Handle_with_policy( const T1& t1, const T2& t2, const T3& t3) : rep( Rep(t1,t2,t3)) {} 01271 01274 template <class T1, class T2, class T3, class T4> 01275 Handle_with_policy( const T1& t1, const T2& t2, const T3& t3, const T4& t4) 01276 : rep( Rep( t1, t2, t3, t4)) {} 01277 01280 template <class T1, class T2, class T3, class T4, class T5> 01281 Handle_with_policy( const T1& t1, const T2& t2, const T3& t3, const T4& t4, 01282 const T5& t5) 01283 : rep( Rep( t1, t2, t3, t4, t5)) {} 01284 01287 template <class T1, class T2, class T3, class T4, class T5, class T6> 01288 Handle_with_policy( const T1& t1, const T2& t2, const T3& t3, const T4& t4, 01289 const T5& t5, const T6& t6) 01290 : rep( Rep( t1, t2, t3, t4, t5, t6)) {} 01291 01294 template <class T1, class T2, class T3, class T4, class T5, class T6, 01295 class T7> 01296 Handle_with_policy( const T1& t1, const T2& t2, const T3& t3, const T4& t4, 01297 const T5& t5, const T6& t6, const T7& t7) 01298 : rep( Rep( t1, t2, t3, t4, t5, t6, t7)) {} 01299 01302 template <class T1, class T2, class T3, class T4, class T5, class T6, 01303 class T7, class T8> 01304 Handle_with_policy( const T1& t1, const T2& t2, const T3& t3, const T4& t4, 01305 const T5& t5, const T6& t6, const T7& t7, const T8& t8) 01306 : rep( Rep( t1, t2, t3, t4, t5, t6, t7, t8)) {} 01307 01310 template <class T1, class T2, class T3, class T4, class T5, class T6, 01311 class T7, class T8, class T9> 01312 Handle_with_policy( const T1& t1, const T2& t2, const T3& t3, const T4& t4, 01313 const T5& t5, const T6& t6, const T7& t7, const T8& t8, 01314 const T9& t9) 01315 : rep( Rep( t1, t2, t3, t4, t5, t6, t7, t8, t9)) {} 01316 01318 bool is_identical( const Self& h) const { return this == &h; } 01319 01322 Id_type id() const { return reinterpret_cast<Id_type>(this); } 01323 01326 bool is_shared() const { return false; } 01327 01330 bool is_forwarding() const { return false; } 01331 01333 int union_size() const { return 1; } 01334 01335 // backwards compatible 01336 bool identical( const Self& h) const { return is_identical(h); } 01337 01338 #ifdef CGAL_HANDLE_WITH_POLICY_INTERNAL_TEST 01339 // provide access to pointer for testing only!! 01340 const Rep* test_ptr() const { return *rep; } 01341 // provide access to pointer for testing only!! 01342 bool test_identical_ptr( const Self& h) const { return this == &h; } 01343 #endif // CGAL_HANDLE_WITH_POLICY_INTERNAL_TEST 01344 01345 #ifdef CGAL_USE_LEDA 01346 LEDA_MEMORY( Self) 01347 #endif 01348 }; 01349 01350 /*\brief 01351 * This class' function call operator test whether one handle's \c id is 01352 * less than the \c id of the other handle. 01353 * 01354 * "Less" is defined in terms of the second template argument, 01355 * which defaults to \c std::less<Handle::Id_type> 01356 */ 01357 template <class Handle, class Less = std::less<typename Handle::Id_type> > 01358 class Handle_id_less_than { 01359 public: 01361 typedef bool result_type; 01363 typedef Handle first_argument_type; 01365 typedef Handle second_argument_type; 01367 bool operator () (Handle h1, Handle h2) { 01368 Less is_less; 01369 return is_less(h1.id(), h2.id()); 01370 } 01372 bool operator () (Handle h1, Handle h2) const { 01373 Less is_less; 01374 return is_less(h1.id(), h2.id()); 01375 } 01376 }; 01377 01378 01380 01381 CGAL_END_NAMESPACE 01382 01383 #endif // CGAL_HANDLE_WITH_POLICY_H