BWAPI
|
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