dust3d/thirdparty/cgal/CGAL-5.1/include/CGAL/Handle_for.h

282 lines
6.1 KiB
C++

// Copyright (c) 1999,2001,2003
// Utrecht University (The Netherlands),
// ETH Zurich (Switzerland),
// INRIA Sophia-Antipolis (France),
// Max-Planck-Institute Saarbruecken (Germany),
// and Tel-Aviv University (Israel). All rights reserved.
//
// This file is part of CGAL (www.cgal.org)
//
// $URL: https://github.com/CGAL/cgal/blob/v5.1/STL_Extension/include/CGAL/Handle_for.h $
// $Id: Handle_for.h 8bb22d5 2020-03-26T14:23:37+01:00 Sébastien Loriot
// SPDX-License-Identifier: LGPL-3.0-or-later OR LicenseRef-Commercial
//
//
// Author(s) : Stefan Schirra, Sylvain Pion
#ifndef CGAL_HANDLE_FOR_H
#define CGAL_HANDLE_FOR_H
#include <CGAL/disable_warnings.h>
#include <CGAL/config.h>
#include <CGAL/assertions.h> // for CGAL_assume
#include <boost/config.hpp>
#include <CGAL/memory.h>
#include <algorithm>
#include <cstddef>
#if defined(BOOST_MSVC)
# pragma warning(push)
# pragma warning(disable:4345) // Avoid warning http://msdn.microsoft.com/en-us/library/wewb47ee(VS.80).aspx
#endif
namespace CGAL {
template <class T, class Alloc = CGAL_ALLOCATOR(T) >
class Handle_for
{
// Wrapper that adds the reference counter.
struct RefCounted {
T t;
unsigned int count;
};
typedef std::allocator_traits<Alloc> Alloc_traits;
typedef typename Alloc_traits::template rebind_alloc<RefCounted> Allocator;
typedef std::allocator_traits<Allocator> Allocator_traits;
typedef typename Alloc_traits::template rebind_traits<RefCounted>::pointer pointer;
static Allocator allocator;
pointer ptr_;
public:
typedef T element_type;
typedef std::ptrdiff_t Id_type ;
Handle_for()
{
pointer p = allocator.allocate(1);
new (&(p->t)) element_type(); // we get the warning here
p->count = 1;
ptr_ = p;
}
Handle_for(const element_type& t)
{
pointer p = allocator.allocate(1);
new (&(p->t)) element_type(t);
p->count = 1;
ptr_ = p;
}
Handle_for(element_type && t)
{
pointer p = allocator.allocate(1);
new (&(p->t)) element_type(std::move(t));
p->count = 1;
ptr_ = p;
}
/* I comment this one for now, since it's preventing the automatic conversions
to take place. We'll see if it's a problem later.
template < typename T1 >
Handle_for(const T1& t1)
{
pointer p = allocator.allocate(1);
new (&(p->t)) T(t1);
p->count = 1;
ptr_ = p;
}
*/
template < typename T1, typename T2, typename... Args >
Handle_for(T1 && t1, T2 && t2, Args && ... args)
{
pointer p = allocator.allocate(1);
new (&(p->t)) element_type(std::forward<T1>(t1), std::forward<T2>(t2), std::forward<Args>(args)...);
p->count = 1;
ptr_ = p;
}
Handle_for(const Handle_for& h) noexcept
: ptr_(h.ptr_)
{
CGAL_assume (ptr_->count > 0);
++(ptr_->count);
}
Handle_for&
operator=(const Handle_for& h) noexcept
{
Handle_for tmp = h;
swap(tmp);
return *this;
}
Handle_for&
operator=(const element_type &t)
{
if (is_shared())
*this = Handle_for(t);
else
ptr_->t = t;
return *this;
}
// Note : I don't see a way to make a useful move constructor, apart
// from e.g. using nullptr as a ptr value, but this is drastic.
Handle_for&
operator=(Handle_for && h) noexcept
{
swap(h);
return *this;
}
Handle_for&
operator=(element_type && t)
{
if (is_shared())
*this = Handle_for(std::move(t));
else
ptr_->t = std::move(t);
return *this;
}
~Handle_for()
{
if (--(ptr_->count) == 0) {
Allocator_traits::destroy(allocator, ptr_);
allocator.deallocate( ptr_, 1);
}
}
void
initialize_with(const element_type& t)
{
// kept for backward compatibility. Use operator=(t) instead.
*this = t;
}
Id_type id() const noexcept { return Ptr() - static_cast<T const*>(0); }
bool identical(const Handle_for& h) const noexcept { return Ptr() == h.Ptr(); }
// Ptr() is the "public" access to the pointer to the object.
// The non-const version asserts that the instance is not shared.
const element_type *
Ptr() const noexcept
{
return &(ptr_->t);
}
/*
// The assertion triggers in a couple of places, so I comment it for now.
T *
Ptr()
{
CGAL_assertion(!is_shared());
return &(ptr_->t);
}
*/
bool
is_shared() const noexcept
{
return ptr_->count > 1;
}
bool
unique() const noexcept
{
return !is_shared();
}
long
use_count() const noexcept
{
return ptr_->count;
}
void
swap(Handle_for& h) noexcept
{
std::swap(ptr_, h.ptr_);
}
protected:
void
copy_on_write()
{
if ( is_shared() ) Handle_for(ptr_->t).swap(*this);
}
// ptr() is the protected access to the pointer. Both const and non-const.
// Redundant with Ptr().
element_type *
ptr() noexcept
{ return &(ptr_->t); }
const element_type *
ptr() const noexcept
{ return &(ptr_->t); }
};
template <class T, class Allocator>
typename Handle_for<T, Allocator>::Allocator
Handle_for<T, Allocator>::allocator;
template <class T, class Allocator>
inline
void
swap(Handle_for<T, Allocator> &h1, Handle_for<T, Allocator> &h2)
{
h1.swap(h2);
}
template <class T, class Allocator>
inline
bool
identical(const Handle_for<T, Allocator> &h1,
const Handle_for<T, Allocator> &h2)
{
return h1.identical(h2);
}
template <class T> inline bool identical(const T &t1, const T &t2) { return &t1 == &t2; }
template <class T, class Allocator>
inline
const T&
get_pointee_or_identity(const Handle_for<T, Allocator> &h)
{
return *(h.Ptr());
}
template <class T>
inline
const T&
get_pointee_or_identity(const T &t)
{
return t;
}
} //namespace CGAL
#if defined(BOOST_MSVC)
# pragma warning(pop)
#endif
#include <CGAL/enable_warnings.h>
#endif // CGAL_HANDLE_FOR_H