BWAPI
SPAR/AIModule/BWTA/vendors/CGAL/CGAL/Handle_for.h
Go to the documentation of this file.
00001 // Copyright (c) 1999,2001,2003  Utrecht University (The Netherlands),
00002 // ETH Zurich (Switzerland), Freie Universitaet Berlin (Germany),
00003 // INRIA Sophia-Antipolis (France), Martin-Luther-University Halle-Wittenberg
00004 // (Germany), Max-Planck-Institute Saarbruecken (Germany), RISC Linz (Austria),
00005 // and Tel-Aviv University (Israel).  All rights reserved.
00006 //
00007 // This file is part of CGAL (www.cgal.org); you can redistribute it and/or
00008 // modify it under the terms of the GNU Lesser General Public License as
00009 // published by the Free Software Foundation; version 2.1 of the License.
00010 // See the file LICENSE.LGPL distributed with CGAL.
00011 //
00012 // Licensees holding a valid commercial license may use this file in
00013 // accordance with the commercial license agreement provided with the software.
00014 //
00015 // This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
00016 // WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
00017 //
00018 // $URL: svn+ssh://scm.gforge.inria.fr/svn/cgal/branches/CGAL-3.5-branch/STL_Extension/include/CGAL/Handle_for.h $
00019 // $Id: Handle_for.h 46241 2008-10-13 14:18:24Z afabri $
00020 // 
00021 //
00022 // Author(s)     : Stefan Schirra, Sylvain Pion
00023  
00024 #ifndef CGAL_HANDLE_FOR_H
00025 #define CGAL_HANDLE_FOR_H
00026 
00027 #include <boost/config.hpp>
00028 #include <CGAL/memory.h>
00029 #include <algorithm>
00030 
00031 #if defined(BOOST_MSVC)
00032 #  pragma warning(push)
00033 #  pragma warning(disable:4345) // Avoid warning  http://msdn.microsoft.com/en-us/library/wewb47ee(VS.80).aspx
00034 #endif
00035 CGAL_BEGIN_NAMESPACE
00036 
00037 template <class T, class Alloc = CGAL_ALLOCATOR(T) >
00038 class Handle_for
00039 {
00040     // Wrapper that adds the reference counter.
00041     struct RefCounted {
00042         T t;
00043         unsigned int count;
00044     };
00045 
00046     typedef typename Alloc::template rebind<RefCounted>::other  Allocator;
00047     typedef typename Allocator::pointer                         pointer;
00048 
00049     static Allocator   allocator;
00050     pointer            ptr_;
00051 
00052 public:
00053 
00054     typedef T element_type;
00055 
00056     Handle_for()
00057       : ptr_(allocator.allocate(1))
00058     {
00059         new (&(ptr_->t)) T(); // we get the warning here 
00060         ptr_->count = 1;
00061     }
00062 
00063     Handle_for(const T& t)
00064       : ptr_(allocator.allocate(1))
00065     {
00066         new (&(ptr_->t)) T(t);
00067         ptr_->count = 1;
00068     }
00069 
00070 #ifndef CGAL_CFG_NO_CPP0X_RVALUE_REFERENCE
00071     Handle_for(T && t)
00072       : ptr_(allocator.allocate(1))
00073     {
00074         new (&(ptr_->t)) T(std::move(t));
00075         ptr_->count = 1;
00076     }
00077 #endif
00078 
00079 /* I comment this one for now, since it's preventing the automatic conversions
00080    to take place.  We'll see if it's a problem later.
00081     template < typename T1 >
00082     Handle_for(const T1& t1)
00083       : ptr_(allocator.allocate(1))
00084     {
00085         new (&(ptr_->t)) T(t1);
00086         ptr_->count = 1;
00087     }
00088 */
00089 
00090 #if !defined CGAL_CFG_NO_CPP0X_VARIADIC_TEMPLATES && !defined CGAL_CFG_NO_CPP0X_RVALUE_REFERENCE
00091     template < typename T1, typename T2, typename... Args >
00092     Handle_for(T1 && t1, T2 && t2, Args && ... args)
00093       : ptr_(allocator.allocate(1))
00094     {
00095         new (&(ptr_->t)) T(std::forward<T1>(t1), std::forward<T2>(t2), std::forward<Args>(args)...);
00096         ptr_->count = 1;
00097     }
00098 #else
00099     template < typename T1, typename T2 >
00100     Handle_for(const T1& t1, const T2& t2)
00101       : ptr_(allocator.allocate(1))
00102     {
00103         new (&(ptr_->t)) T(t1, t2);
00104         ptr_->count = 1;
00105     }
00106 
00107     template < typename T1, typename T2, typename T3 >
00108     Handle_for(const T1& t1, const T2& t2, const T3& t3)
00109       : ptr_(allocator.allocate(1))
00110     {
00111         new (&(ptr_->t)) T(t1, t2, t3);
00112         ptr_->count = 1;
00113     }
00114 
00115     template < typename T1, typename T2, typename T3, typename T4 >
00116     Handle_for(const T1& t1, const T2& t2, const T3& t3, const T4& t4)
00117       : ptr_(allocator.allocate(1))
00118     {
00119         new (&(ptr_->t)) T(t1, t2, t3, t4);
00120         ptr_->count = 1;
00121     }
00122 #endif // CGAL_CFG_NO_CPP0X_VARIADIC_TEMPLATES
00123 
00124     Handle_for(const Handle_for& h)
00125       : ptr_(h.ptr_)
00126     {
00127         ++(ptr_->count);
00128     }
00129 
00130     Handle_for&
00131     operator=(const Handle_for& h)
00132     {
00133         Handle_for tmp = h;
00134         swap(tmp);
00135         return *this;
00136     }
00137 
00138     Handle_for&
00139     operator=(const T &t)
00140     {
00141         if (is_shared())
00142             *this = Handle_for(t);
00143         else
00144             ptr_->t = t;
00145 
00146         return *this;
00147     }
00148 
00149 #ifndef CGAL_CFG_NO_CPP0X_RVALUE_REFERENCE
00150     // Note : I don't see a way to make a useful move constructor, apart
00151     //        from e.g. using NULL as a ptr value, but this is drastic.
00152 
00153     Handle_for&
00154     operator=(Handle_for && h)
00155     {
00156         swap(h);
00157         return *this;
00158     }
00159 
00160     Handle_for&
00161     operator=(T && t)
00162     {
00163         if (is_shared())
00164             *this = Handle_for(std::move(t));
00165         else
00166             ptr_->t = std::move(t);
00167 
00168         return *this;
00169     }
00170 #endif
00171 
00172     ~Handle_for()
00173     {
00174       if (! is_shared() ) {
00175           allocator.destroy( ptr_);
00176           allocator.deallocate( ptr_, 1);
00177       }
00178       else
00179           --(ptr_->count);
00180     }
00181 
00182     void
00183     initialize_with(const T& t)
00184     {
00185         // kept for backward compatibility.  Use operator=(t) instead.
00186         *this = t;
00187     }
00188 
00189     bool
00190     identical(const Handle_for& h) const
00191     { return ptr_ == h.ptr_; }
00192 
00193     long int
00194     id() const
00195     { return reinterpret_cast<long int>(&*ptr_); }
00196 
00197     // Ptr() is the "public" access to the pointer to the object.
00198     // The non-const version asserts that the instance is not shared.
00199     const T *
00200     Ptr() const
00201     {
00202        return &(ptr_->t);
00203     }
00204 
00205     /*
00206     // The assertion triggers in a couple of places, so I comment it for now.
00207     T *
00208     Ptr()
00209     {
00210       CGAL_assertion(!is_shared());
00211       return &(ptr_->t);
00212     }
00213     */
00214 
00215     bool
00216     is_shared() const
00217     {
00218         return ptr_->count > 1;
00219     }
00220 
00221     bool
00222     unique() const
00223     {
00224         return !is_shared();
00225     }
00226 
00227     long
00228     use_count() const
00229     {
00230         return ptr_->count;
00231     }
00232 
00233     void
00234     swap(Handle_for& h)
00235     {
00236       std::swap(ptr_, h.ptr_);
00237     }
00238 
00239 protected:
00240 
00241     void
00242     copy_on_write()
00243     {
00244       if ( is_shared() )
00245       {
00246         pointer tmp_ptr = allocator.allocate(1);
00247         new (&(tmp_ptr->t)) T(ptr_->t);
00248         tmp_ptr->count = 1;
00249         --(ptr_->count);
00250         ptr_ = tmp_ptr;
00251       }
00252     }
00253 
00254     // ptr() is the protected access to the pointer.  Both const and non-const.
00255     // Redundant with Ptr().
00256     T *
00257     ptr()
00258     { return &(ptr_->t); }
00259 
00260     const T *
00261     ptr() const
00262     { return &(ptr_->t); }
00263 };
00264 
00265 
00266 template <class T, class Allocator>
00267 typename Handle_for<T, Allocator>::Allocator
00268 Handle_for<T, Allocator>::allocator;
00269 
00270 template <class T, class Allocator>
00271 inline
00272 void
00273 swap(Handle_for<T, Allocator> &h1, Handle_for<T, Allocator> &h2)
00274 {
00275     h1.swap(h2);
00276 }
00277 
00278 template <class T, class Allocator>
00279 inline
00280 bool
00281 identical(const Handle_for<T, Allocator> &h1,
00282           const Handle_for<T, Allocator> &h2)
00283 {
00284     return h1.identical(h2);
00285 }
00286 
00287 template <class T>
00288 inline
00289 bool
00290 identical(const T &t1, const T &t2)
00291 {
00292     return &t1 == &t2;
00293 }
00294 
00295 template <class T, class Allocator>
00296 inline
00297 const T&
00298 get(const Handle_for<T, Allocator> &h)
00299 {
00300     return *(h.Ptr());
00301 }
00302 
00303 template <class T>
00304 inline
00305 const T&
00306 get(const T &t)
00307 {
00308     return t;
00309 }
00310 
00311 CGAL_END_NAMESPACE
00312 
00313 #if defined(BOOST_MSVC)
00314 #  pragma warning(pop)
00315 #endif
00316 
00317 #endif // CGAL_HANDLE_FOR_H
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines