llvm-project/libcxx/include/memory

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

961 lines
34 KiB
Plaintext
Raw Normal View History

2010-05-12 03:42:16 +08:00
// -*- C++ -*-
//===-------------------------- memory ------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
2010-05-12 03:42:16 +08:00
//
//===----------------------------------------------------------------------===//
#ifndef _LIBCPP_MEMORY
#define _LIBCPP_MEMORY
/*
memory synopsis
namespace std
{
struct allocator_arg_t { };
inline constexpr allocator_arg_t allocator_arg = allocator_arg_t();
2010-05-12 03:42:16 +08:00
template <class T, class Alloc> struct uses_allocator;
template <class Ptr>
struct pointer_traits
{
typedef Ptr pointer;
typedef <details> element_type;
typedef <details> difference_type;
2010-05-12 03:42:16 +08:00
template <class U> using rebind = <details>;
2010-05-12 03:42:16 +08:00
static pointer pointer_to(<details>);
};
template <class T>
struct pointer_traits<T*>
{
typedef T* pointer;
typedef T element_type;
typedef ptrdiff_t difference_type;
template <class U> using rebind = U*;
static pointer pointer_to(<details>) noexcept; // constexpr in C++20
};
template <class T> constexpr T* to_address(T* p) noexcept; // C++20
template <class Ptr> constexpr auto to_address(const Ptr& p) noexcept; // C++20
2010-05-12 03:42:16 +08:00
template <class Alloc>
struct allocator_traits
{
typedef Alloc allocator_type;
typedef typename allocator_type::value_type
value_type;
typedef Alloc::pointer | value_type* pointer;
typedef Alloc::const_pointer
| pointer_traits<pointer>::rebind<const value_type>
const_pointer;
typedef Alloc::void_pointer
| pointer_traits<pointer>::rebind<void>
void_pointer;
typedef Alloc::const_void_pointer
| pointer_traits<pointer>::rebind<const void>
const_void_pointer;
typedef Alloc::difference_type
2010-11-18 09:40:00 +08:00
| pointer_traits<pointer>::difference_type
difference_type;
typedef Alloc::size_type
| make_unsigned<difference_type>::type
size_type;
2010-05-12 03:42:16 +08:00
typedef Alloc::propagate_on_container_copy_assignment
| false_type propagate_on_container_copy_assignment;
typedef Alloc::propagate_on_container_move_assignment
| false_type propagate_on_container_move_assignment;
typedef Alloc::propagate_on_container_swap
| false_type propagate_on_container_swap;
typedef Alloc::is_always_equal
| is_empty is_always_equal;
2010-05-12 03:42:16 +08:00
template <class T> using rebind_alloc = Alloc::rebind<T>::other | Alloc<T, Args...>;
2010-05-12 03:42:16 +08:00
template <class T> using rebind_traits = allocator_traits<rebind_alloc<T>>;
static pointer allocate(allocator_type& a, size_type n); // constexpr and [[nodiscard]] in C++20
static pointer allocate(allocator_type& a, size_type n, const_void_pointer hint); // constexpr and [[nodiscard]] in C++20
2010-05-12 03:42:16 +08:00
static void deallocate(allocator_type& a, pointer p, size_type n) noexcept; // constexpr in C++20
2010-05-12 03:42:16 +08:00
template <class T, class... Args>
static void construct(allocator_type& a, T* p, Args&&... args); // constexpr in C++20
2010-05-12 03:42:16 +08:00
template <class T>
static void destroy(allocator_type& a, T* p); // constexpr in C++20
2010-05-12 03:42:16 +08:00
static size_type max_size(const allocator_type& a); // noexcept in C++14, constexpr in C++20
static allocator_type select_on_container_copy_construction(const allocator_type& a); // constexpr in C++20
2010-05-12 03:42:16 +08:00
};
template <>
class allocator<void> // deprecated in C++17, removed in C++20
2010-05-12 03:42:16 +08:00
{
public:
typedef void* pointer;
typedef const void* const_pointer;
typedef void value_type;
template <class _Up> struct rebind {typedef allocator<_Up> other;};
};
template <class T>
class allocator
{
public:
typedef size_t size_type;
typedef ptrdiff_t difference_type;
typedef T* pointer; // deprecated in C++17, removed in C++20
typedef const T* const_pointer; // deprecated in C++17, removed in C++20
typedef typename add_lvalue_reference<T>::type
reference; // deprecated in C++17, removed in C++20
typedef typename add_lvalue_reference<const T>::type
const_reference; // deprecated in C++17, removed in C++20
2010-05-12 03:42:16 +08:00
typedef T value_type;
template <class U> struct rebind {typedef allocator<U> other;}; // deprecated in C++17, removed in C++20
typedef true_type propagate_on_container_move_assignment;
typedef true_type is_always_equal;
2010-05-12 03:42:16 +08:00
constexpr allocator() noexcept; // constexpr in C++20
constexpr allocator(const allocator&) noexcept; // constexpr in C++20
template <class U>
constexpr allocator(const allocator<U>&) noexcept; // constexpr in C++20
~allocator(); // constexpr in C++20
pointer address(reference x) const noexcept; // deprecated in C++17, removed in C++20
const_pointer address(const_reference x) const noexcept; // deprecated in C++17, removed in C++20
T* allocate(size_t n, const void* hint); // deprecated in C++17, removed in C++20
T* allocate(size_t n); // constexpr in C++20
void deallocate(T* p, size_t n) noexcept; // constexpr in C++20
size_type max_size() const noexcept; // deprecated in C++17, removed in C++20
template<class U, class... Args>
void construct(U* p, Args&&... args); // deprecated in C++17, removed in C++20
template <class U>
void destroy(U* p); // deprecated in C++17, removed in C++20
2010-05-12 03:42:16 +08:00
};
template <class T, class U>
bool operator==(const allocator<T>&, const allocator<U>&) noexcept; // constexpr in C++20
2010-05-12 03:42:16 +08:00
template <class T, class U>
bool operator!=(const allocator<T>&, const allocator<U>&) noexcept; // constexpr in C++20
2010-05-12 03:42:16 +08:00
template <class OutputIterator, class T>
class raw_storage_iterator
: public iterator<output_iterator_tag, void, void, void, void> // until C++17
2010-05-12 03:42:16 +08:00
{
public:
explicit raw_storage_iterator(OutputIterator x);
raw_storage_iterator& operator*();
raw_storage_iterator& operator=(const T& element);
raw_storage_iterator& operator++();
raw_storage_iterator operator++(int);
};
template <class T> pair<T*,ptrdiff_t> get_temporary_buffer(ptrdiff_t n) noexcept;
template <class T> void return_temporary_buffer(T* p) noexcept;
template <class T> T* addressof(T& r) noexcept;
template <class T> T* addressof(const T&& r) noexcept = delete;
2010-05-12 03:42:16 +08:00
template <class InputIterator, class ForwardIterator>
ForwardIterator
uninitialized_copy(InputIterator first, InputIterator last, ForwardIterator result);
template <class InputIterator, class Size, class ForwardIterator>
ForwardIterator
uninitialized_copy_n(InputIterator first, Size n, ForwardIterator result);
2010-05-12 03:42:16 +08:00
template <class ForwardIterator, class T>
void uninitialized_fill(ForwardIterator first, ForwardIterator last, const T& x);
template <class ForwardIterator, class Size, class T>
2010-11-19 00:13:03 +08:00
ForwardIterator
uninitialized_fill_n(ForwardIterator first, Size n, const T& x);
2010-05-12 03:42:16 +08:00
template <class T, class ...Args>
constexpr T* construct_at(T* location, Args&& ...args); // since C++20
template <class T>
void destroy_at(T* location); // constexpr in C++20
template <class ForwardIterator>
void destroy(ForwardIterator first, ForwardIterator last); // constexpr in C++20
template <class ForwardIterator, class Size>
ForwardIterator destroy_n(ForwardIterator first, Size n); // constexpr in C++20
template <class InputIterator, class ForwardIterator>
ForwardIterator uninitialized_move(InputIterator first, InputIterator last, ForwardIterator result);
template <class InputIterator, class Size, class ForwardIterator>
pair<InputIterator,ForwardIterator> uninitialized_move_n(InputIterator first, Size n, ForwardIterator result);
template <class ForwardIterator>
void uninitialized_value_construct(ForwardIterator first, ForwardIterator last);
template <class ForwardIterator, class Size>
ForwardIterator uninitialized_value_construct_n(ForwardIterator first, Size n);
template <class ForwardIterator>
void uninitialized_default_construct(ForwardIterator first, ForwardIterator last);
template <class ForwardIterator, class Size>
ForwardIterator uninitialized_default_construct_n(ForwardIterator first, Size n);
template <class Y> struct auto_ptr_ref {}; // deprecated in C++11, removed in C++17
2010-05-12 03:42:16 +08:00
template<class X>
class auto_ptr // deprecated in C++11, removed in C++17
2010-05-12 03:42:16 +08:00
{
public:
typedef X element_type;
explicit auto_ptr(X* p =0) throw();
auto_ptr(auto_ptr&) throw();
template<class Y> auto_ptr(auto_ptr<Y>&) throw();
auto_ptr& operator=(auto_ptr&) throw();
template<class Y> auto_ptr& operator=(auto_ptr<Y>&) throw();
auto_ptr& operator=(auto_ptr_ref<X> r) throw();
~auto_ptr() throw();
typename add_lvalue_reference<X>::type operator*() const throw();
X* operator->() const throw();
X* get() const throw();
X* release() throw();
void reset(X* p =0) throw();
auto_ptr(auto_ptr_ref<X>) throw();
template<class Y> operator auto_ptr_ref<Y>() throw();
template<class Y> operator auto_ptr<Y>() throw();
};
2010-08-20 02:39:17 +08:00
template <class T>
struct default_delete
{
constexpr default_delete() noexcept = default;
template <class U> default_delete(const default_delete<U>&) noexcept;
2010-08-20 02:39:17 +08:00
void operator()(T*) const noexcept;
2010-08-20 02:39:17 +08:00
};
template <class T>
struct default_delete<T[]>
{
constexpr default_delete() noexcept = default;
void operator()(T*) const noexcept;
2010-08-20 02:39:17 +08:00
template <class U> void operator()(U*) const = delete;
};
template <class T, class D = default_delete<T>>
class unique_ptr
{
public:
typedef see below pointer;
typedef T element_type;
typedef D deleter_type;
// constructors
constexpr unique_ptr() noexcept;
explicit unique_ptr(pointer p) noexcept;
unique_ptr(pointer p, see below d1) noexcept;
unique_ptr(pointer p, see below d2) noexcept;
unique_ptr(unique_ptr&& u) noexcept;
unique_ptr(nullptr_t) noexcept : unique_ptr() { }
2010-08-20 02:39:17 +08:00
template <class U, class E>
unique_ptr(unique_ptr<U, E>&& u) noexcept;
2010-08-20 02:39:17 +08:00
template <class U>
unique_ptr(auto_ptr<U>&& u) noexcept; // removed in C++17
2010-08-20 02:39:17 +08:00
// destructor
~unique_ptr();
// assignment
unique_ptr& operator=(unique_ptr&& u) noexcept;
template <class U, class E> unique_ptr& operator=(unique_ptr<U, E>&& u) noexcept;
unique_ptr& operator=(nullptr_t) noexcept;
2010-08-20 02:39:17 +08:00
// observers
typename add_lvalue_reference<T>::type operator*() const;
pointer operator->() const noexcept;
pointer get() const noexcept;
deleter_type& get_deleter() noexcept;
const deleter_type& get_deleter() const noexcept;
explicit operator bool() const noexcept;
2010-08-20 02:39:17 +08:00
// modifiers
pointer release() noexcept;
void reset(pointer p = pointer()) noexcept;
void swap(unique_ptr& u) noexcept;
2010-08-20 02:39:17 +08:00
};
template <class T, class D>
class unique_ptr<T[], D>
{
public:
typedef implementation-defined pointer;
typedef T element_type;
typedef D deleter_type;
// constructors
constexpr unique_ptr() noexcept;
explicit unique_ptr(pointer p) noexcept;
unique_ptr(pointer p, see below d) noexcept;
unique_ptr(pointer p, see below d) noexcept;
unique_ptr(unique_ptr&& u) noexcept;
unique_ptr(nullptr_t) noexcept : unique_ptr() { }
2010-08-20 02:39:17 +08:00
// destructor
~unique_ptr();
2010-08-20 02:39:17 +08:00
// assignment
unique_ptr& operator=(unique_ptr&& u) noexcept;
unique_ptr& operator=(nullptr_t) noexcept;
2010-08-20 02:39:17 +08:00
// observers
T& operator[](size_t i) const;
pointer get() const noexcept;
deleter_type& get_deleter() noexcept;
const deleter_type& get_deleter() const noexcept;
explicit operator bool() const noexcept;
2010-08-20 02:39:17 +08:00
// modifiers
pointer release() noexcept;
void reset(pointer p = pointer()) noexcept;
void reset(nullptr_t) noexcept;
template <class U> void reset(U) = delete;
void swap(unique_ptr& u) noexcept;
2010-08-20 02:39:17 +08:00
};
template <class T, class D>
void swap(unique_ptr<T, D>& x, unique_ptr<T, D>& y) noexcept;
2010-08-20 02:39:17 +08:00
template <class T1, class D1, class T2, class D2>
bool operator==(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y);
template <class T1, class D1, class T2, class D2>
bool operator!=(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y);
template <class T1, class D1, class T2, class D2>
bool operator<(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y);
template <class T1, class D1, class T2, class D2>
bool operator<=(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y);
template <class T1, class D1, class T2, class D2>
bool operator>(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y);
template <class T1, class D1, class T2, class D2>
bool operator>=(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y);
template <class T, class D>
bool operator==(const unique_ptr<T, D>& x, nullptr_t) noexcept;
template <class T, class D>
bool operator==(nullptr_t, const unique_ptr<T, D>& y) noexcept;
template <class T, class D>
bool operator!=(const unique_ptr<T, D>& x, nullptr_t) noexcept;
template <class T, class D>
bool operator!=(nullptr_t, const unique_ptr<T, D>& y) noexcept;
template <class T, class D>
bool operator<(const unique_ptr<T, D>& x, nullptr_t);
template <class T, class D>
bool operator<(nullptr_t, const unique_ptr<T, D>& y);
template <class T, class D>
bool operator<=(const unique_ptr<T, D>& x, nullptr_t);
template <class T, class D>
bool operator<=(nullptr_t, const unique_ptr<T, D>& y);
template <class T, class D>
bool operator>(const unique_ptr<T, D>& x, nullptr_t);
template <class T, class D>
bool operator>(nullptr_t, const unique_ptr<T, D>& y);
template <class T, class D>
bool operator>=(const unique_ptr<T, D>& x, nullptr_t);
template <class T, class D>
bool operator>=(nullptr_t, const unique_ptr<T, D>& y);
2010-08-20 02:39:17 +08:00
class bad_weak_ptr
: public std::exception
{
bad_weak_ptr() noexcept;
2010-08-20 02:39:17 +08:00
};
template<class T, class... Args> unique_ptr<T> make_unique(Args&&... args); // C++14
template<class T> unique_ptr<T> make_unique(size_t n); // C++14
template<class T, class... Args> unspecified make_unique(Args&&...) = delete; // C++14, T == U[N]
template<class E, class T, class Y, class D>
basic_ostream<E, T>& operator<< (basic_ostream<E, T>& os, unique_ptr<Y, D> const& p);
2010-08-20 02:39:17 +08:00
template<class T>
class shared_ptr
{
public:
typedef T element_type;
typedef weak_ptr<T> weak_type; // C++17
2010-08-20 02:39:17 +08:00
// constructors:
constexpr shared_ptr() noexcept;
2010-08-20 02:39:17 +08:00
template<class Y> explicit shared_ptr(Y* p);
template<class Y, class D> shared_ptr(Y* p, D d);
template<class Y, class D, class A> shared_ptr(Y* p, D d, A a);
template <class D> shared_ptr(nullptr_t p, D d);
template <class D, class A> shared_ptr(nullptr_t p, D d, A a);
template<class Y> shared_ptr(const shared_ptr<Y>& r, T *p) noexcept;
shared_ptr(const shared_ptr& r) noexcept;
template<class Y> shared_ptr(const shared_ptr<Y>& r) noexcept;
shared_ptr(shared_ptr&& r) noexcept;
template<class Y> shared_ptr(shared_ptr<Y>&& r) noexcept;
2010-08-20 02:39:17 +08:00
template<class Y> explicit shared_ptr(const weak_ptr<Y>& r);
template<class Y> shared_ptr(auto_ptr<Y>&& r); // removed in C++17
2010-08-20 02:39:17 +08:00
template <class Y, class D> shared_ptr(unique_ptr<Y, D>&& r);
shared_ptr(nullptr_t) : shared_ptr() { }
// destructor:
~shared_ptr();
// assignment:
shared_ptr& operator=(const shared_ptr& r) noexcept;
template<class Y> shared_ptr& operator=(const shared_ptr<Y>& r) noexcept;
shared_ptr& operator=(shared_ptr&& r) noexcept;
2010-08-20 02:39:17 +08:00
template<class Y> shared_ptr& operator=(shared_ptr<Y>&& r);
template<class Y> shared_ptr& operator=(auto_ptr<Y>&& r); // removed in C++17
2010-08-20 02:39:17 +08:00
template <class Y, class D> shared_ptr& operator=(unique_ptr<Y, D>&& r);
// modifiers:
void swap(shared_ptr& r) noexcept;
void reset() noexcept;
2010-08-20 02:39:17 +08:00
template<class Y> void reset(Y* p);
template<class Y, class D> void reset(Y* p, D d);
template<class Y, class D, class A> void reset(Y* p, D d, A a);
// observers:
T* get() const noexcept;
T& operator*() const noexcept;
T* operator->() const noexcept;
long use_count() const noexcept;
bool unique() const noexcept;
explicit operator bool() const noexcept;
template<class U> bool owner_before(shared_ptr<U> const& b) const noexcept;
template<class U> bool owner_before(weak_ptr<U> const& b) const noexcept;
2010-08-20 02:39:17 +08:00
};
template<class T>
shared_ptr(weak_ptr<T>) -> shared_ptr<T>;
template<class T, class D>
shared_ptr(unique_ptr<T, D>) -> shared_ptr<T>;
2010-08-20 02:39:17 +08:00
// shared_ptr comparisons:
template<class T, class U>
bool operator==(shared_ptr<T> const& a, shared_ptr<U> const& b) noexcept;
2010-08-20 02:39:17 +08:00
template<class T, class U>
bool operator!=(shared_ptr<T> const& a, shared_ptr<U> const& b) noexcept;
2010-08-20 02:39:17 +08:00
template<class T, class U>
bool operator<(shared_ptr<T> const& a, shared_ptr<U> const& b) noexcept;
2010-08-20 02:39:17 +08:00
template<class T, class U>
bool operator>(shared_ptr<T> const& a, shared_ptr<U> const& b) noexcept;
2010-08-20 02:39:17 +08:00
template<class T, class U>
bool operator<=(shared_ptr<T> const& a, shared_ptr<U> const& b) noexcept;
2010-08-20 02:39:17 +08:00
template<class T, class U>
bool operator>=(shared_ptr<T> const& a, shared_ptr<U> const& b) noexcept;
template <class T>
bool operator==(const shared_ptr<T>& x, nullptr_t) noexcept;
template <class T>
bool operator==(nullptr_t, const shared_ptr<T>& y) noexcept;
template <class T>
bool operator!=(const shared_ptr<T>& x, nullptr_t) noexcept;
template <class T>
bool operator!=(nullptr_t, const shared_ptr<T>& y) noexcept;
template <class T>
bool operator<(const shared_ptr<T>& x, nullptr_t) noexcept;
template <class T>
bool operator<(nullptr_t, const shared_ptr<T>& y) noexcept;
template <class T>
bool operator<=(const shared_ptr<T>& x, nullptr_t) noexcept;
template <class T>
bool operator<=(nullptr_t, const shared_ptr<T>& y) noexcept;
template <class T>
bool operator>(const shared_ptr<T>& x, nullptr_t) noexcept;
template <class T>
bool operator>(nullptr_t, const shared_ptr<T>& y) noexcept;
template <class T>
bool operator>=(const shared_ptr<T>& x, nullptr_t) noexcept;
template <class T>
bool operator>=(nullptr_t, const shared_ptr<T>& y) noexcept;
2010-08-20 02:39:17 +08:00
// shared_ptr specialized algorithms:
template<class T> void swap(shared_ptr<T>& a, shared_ptr<T>& b) noexcept;
2010-08-20 02:39:17 +08:00
// shared_ptr casts:
template<class T, class U>
shared_ptr<T> static_pointer_cast(shared_ptr<U> const& r) noexcept;
2010-08-20 02:39:17 +08:00
template<class T, class U>
shared_ptr<T> dynamic_pointer_cast(shared_ptr<U> const& r) noexcept;
2010-08-20 02:39:17 +08:00
template<class T, class U>
shared_ptr<T> const_pointer_cast(shared_ptr<U> const& r) noexcept;
2010-08-20 02:39:17 +08:00
// shared_ptr I/O:
template<class E, class T, class Y>
basic_ostream<E, T>& operator<< (basic_ostream<E, T>& os, shared_ptr<Y> const& p);
// shared_ptr get_deleter:
template<class D, class T> D* get_deleter(shared_ptr<T> const& p) noexcept;
2010-08-20 02:39:17 +08:00
template<class T, class... Args>
shared_ptr<T> make_shared(Args&&... args);
template<class T, class A, class... Args>
shared_ptr<T> allocate_shared(const A& a, Args&&... args);
template<class T>
class weak_ptr
{
public:
typedef T element_type;
// constructors
constexpr weak_ptr() noexcept;
template<class Y> weak_ptr(shared_ptr<Y> const& r) noexcept;
weak_ptr(weak_ptr const& r) noexcept;
template<class Y> weak_ptr(weak_ptr<Y> const& r) noexcept;
weak_ptr(weak_ptr&& r) noexcept; // C++14
template<class Y> weak_ptr(weak_ptr<Y>&& r) noexcept; // C++14
2010-08-20 02:39:17 +08:00
// destructor
~weak_ptr();
// assignment
weak_ptr& operator=(weak_ptr const& r) noexcept;
template<class Y> weak_ptr& operator=(weak_ptr<Y> const& r) noexcept;
template<class Y> weak_ptr& operator=(shared_ptr<Y> const& r) noexcept;
weak_ptr& operator=(weak_ptr&& r) noexcept; // C++14
template<class Y> weak_ptr& operator=(weak_ptr<Y>&& r) noexcept; // C++14
2010-08-20 02:39:17 +08:00
// modifiers
void swap(weak_ptr& r) noexcept;
void reset() noexcept;
2010-08-20 02:39:17 +08:00
// observers
long use_count() const noexcept;
bool expired() const noexcept;
shared_ptr<T> lock() const noexcept;
template<class U> bool owner_before(shared_ptr<U> const& b) const noexcept;
template<class U> bool owner_before(weak_ptr<U> const& b) const noexcept;
2010-08-20 02:39:17 +08:00
};
template<class T>
weak_ptr(shared_ptr<T>) -> weak_ptr<T>;
2010-08-20 02:39:17 +08:00
// weak_ptr specialized algorithms:
template<class T> void swap(weak_ptr<T>& a, weak_ptr<T>& b) noexcept;
2010-08-20 02:39:17 +08:00
// class owner_less:
template<class T> struct owner_less;
template<class T>
struct owner_less<shared_ptr<T> >
2010-08-20 02:39:17 +08:00
: binary_function<shared_ptr<T>, shared_ptr<T>, bool>
{
typedef bool result_type;
bool operator()(shared_ptr<T> const&, shared_ptr<T> const&) const noexcept;
bool operator()(shared_ptr<T> const&, weak_ptr<T> const&) const noexcept;
bool operator()(weak_ptr<T> const&, shared_ptr<T> const&) const noexcept;
2010-08-20 02:39:17 +08:00
};
template<class T>
struct owner_less<weak_ptr<T> >
2010-08-20 02:39:17 +08:00
: binary_function<weak_ptr<T>, weak_ptr<T>, bool>
{
typedef bool result_type;
bool operator()(weak_ptr<T> const&, weak_ptr<T> const&) const noexcept;
bool operator()(shared_ptr<T> const&, weak_ptr<T> const&) const noexcept;
bool operator()(weak_ptr<T> const&, shared_ptr<T> const&) const noexcept;
};
template <> // Added in C++14
struct owner_less<void>
{
template <class _Tp, class _Up>
bool operator()( shared_ptr<_Tp> const& __x, shared_ptr<_Up> const& __y) const noexcept;
template <class _Tp, class _Up>
bool operator()( shared_ptr<_Tp> const& __x, weak_ptr<_Up> const& __y) const noexcept;
template <class _Tp, class _Up>
bool operator()( weak_ptr<_Tp> const& __x, shared_ptr<_Up> const& __y) const noexcept;
template <class _Tp, class _Up>
bool operator()( weak_ptr<_Tp> const& __x, weak_ptr<_Up> const& __y) const noexcept;
typedef void is_transparent;
2010-08-20 02:39:17 +08:00
};
template<class T>
class enable_shared_from_this
{
protected:
constexpr enable_shared_from_this() noexcept;
enable_shared_from_this(enable_shared_from_this const&) noexcept;
enable_shared_from_this& operator=(enable_shared_from_this const&) noexcept;
2010-08-20 02:39:17 +08:00
~enable_shared_from_this();
public:
shared_ptr<T> shared_from_this();
shared_ptr<T const> shared_from_this() const;
};
template<class T>
bool atomic_is_lock_free(const shared_ptr<T>* p);
template<class T>
shared_ptr<T> atomic_load(const shared_ptr<T>* p);
template<class T>
shared_ptr<T> atomic_load_explicit(const shared_ptr<T>* p, memory_order mo);
template<class T>
void atomic_store(shared_ptr<T>* p, shared_ptr<T> r);
template<class T>
void atomic_store_explicit(shared_ptr<T>* p, shared_ptr<T> r, memory_order mo);
template<class T>
shared_ptr<T> atomic_exchange(shared_ptr<T>* p, shared_ptr<T> r);
template<class T>
shared_ptr<T>
atomic_exchange_explicit(shared_ptr<T>* p, shared_ptr<T> r, memory_order mo);
template<class T>
bool
atomic_compare_exchange_weak(shared_ptr<T>* p, shared_ptr<T>* v, shared_ptr<T> w);
template<class T>
bool
atomic_compare_exchange_strong( shared_ptr<T>* p, shared_ptr<T>* v, shared_ptr<T> w);
template<class T>
bool
atomic_compare_exchange_weak_explicit(shared_ptr<T>* p, shared_ptr<T>* v,
shared_ptr<T> w, memory_order success,
memory_order failure);
template<class T>
bool
atomic_compare_exchange_strong_explicit(shared_ptr<T>* p, shared_ptr<T>* v,
shared_ptr<T> w, memory_order success,
memory_order failure);
// Hash support
template <class T> struct hash;
template <class T, class D> struct hash<unique_ptr<T, D> >;
template <class T> struct hash<shared_ptr<T> >;
template <class T, class Alloc>
inline constexpr bool uses_allocator_v = uses_allocator<T, Alloc>::value;
2010-08-20 02:39:17 +08:00
// Pointer safety
enum class pointer_safety { relaxed, preferred, strict }; // since C++11
void declare_reachable(void *p); // since C++11
template <class T> T *undeclare_reachable(T *p); // since C++11
void declare_no_pointers(char *p, size_t n); // since C++11
void undeclare_no_pointers(char *p, size_t n); // since C++11
pointer_safety get_pointer_safety() noexcept; // since C++11
2010-08-20 02:39:17 +08:00
2010-05-12 03:42:16 +08:00
void* align(size_t alignment, size_t size, void*& ptr, size_t& space);
} // std
*/
#include <__config>
#include <__functional_base>
#include <__memory/addressof.h>
#include <__memory/allocation_guard.h>
#include <__memory/allocator.h>
#include <__memory/allocator_traits.h>
#include <__memory/compressed_pair.h>
#include <__memory/construct_at.h>
#include <__memory/pointer_safety.h>
#include <__memory/pointer_traits.h>
#include <__memory/raw_storage_iterator.h>
#include <__memory/shared_ptr.h>
#include <__memory/temporary_buffer.h>
#include <__memory/uninitialized_algorithms.h>
#include <__memory/unique_ptr.h>
#include <compare>
#include <cstddef>
#include <cstdint>
#include <cstring>
#include <iosfwd>
#include <iterator>
#include <new>
#include <stdexcept>
#include <tuple>
#include <type_traits>
#include <typeinfo>
#include <utility>
#include <version>
Implement [util.smartptr.shared.atomic]. This is the last unimplemented section in libc++. This requires a recompiled dylib. Failure to rebuild the dylib will result in a link-time error if and only if the functions from [util.smartptr.shared.atomic] are used. The implementation is not lock free. After considerable thought, I know of no way to make the implementation lock free. Ideas welcome along that front. But changing the ABI of shared_ptr is not on the table at this point. The mutex used to lock these function is encapsulated by std::__sp_mut. The only thing the client knows about std::__sp_mut is that it has a void* data member, can't be constructed, and has lock and unlock members. Within the binary __sp_mut is currently implemented as a pointer to a std::mutex. That can change in the future without disturbing the ABI (as long as sizeof(__sp_mut) remains constant. I specifically did not make __sp_mut a spin lock as I have a pathological distrust of spin locks. Testing on OS X reveals that the use of std::mutex in this role is not a large performance penalty as long as the contention for the mutex is low (more likely to get the lock than to have to wait). In the future we can still make __sp_mut a spin lock if that is what is desired (without ABI damage). The dylib contains 16 __sp_mut's to be chosen based on the hash of the address of the shared_ptr. The constant 16 is a ball-park reasonable space/time tradeoff. std::hash<T*> was changed to call __murmur2_or_cityhash, instead of the identity function. I had thought we had already done this, but I was mistaken. All of this is under #if __has_feature(cxx_atomic) even though the implementation is not lock free, because the signatures require access to std::memory_order, which is currently available only under __has_feature(cxx_atomic). llvm-svn: 160940
2012-07-30 09:40:57 +08:00
#if _LIBCPP_STD_VER <= 14 || defined(_LIBCPP_ENABLE_CXX17_REMOVED_AUTO_PTR)
# include <__memory/auto_ptr.h>
#endif
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
2010-05-12 03:42:16 +08:00
#pragma GCC system_header
#endif
2010-05-12 03:42:16 +08:00
_LIBCPP_PUSH_MACROS
#include <__undef_macros>
2010-05-12 03:42:16 +08:00
_LIBCPP_BEGIN_NAMESPACE_STD
template <class _Alloc, class _Ptr>
_LIBCPP_INLINE_VISIBILITY
void __construct_forward_with_exception_guarantees(_Alloc& __a, _Ptr __begin1, _Ptr __end1, _Ptr& __begin2) {
static_assert(__is_cpp17_move_insertable<_Alloc>::value,
"The specified type does not meet the requirements of Cpp17MoveInsertable");
typedef allocator_traits<_Alloc> _Traits;
for (; __begin1 != __end1; ++__begin1, (void)++__begin2) {
_Traits::construct(__a, _VSTD::__to_address(__begin2),
#ifdef _LIBCPP_NO_EXCEPTIONS
_VSTD::move(*__begin1)
#else
_VSTD::move_if_noexcept(*__begin1)
#endif
);
}
}
template <class _Alloc, class _Tp, typename enable_if<
(__is_default_allocator<_Alloc>::value || !__has_construct<_Alloc, _Tp*, _Tp>::value) &&
is_trivially_move_constructible<_Tp>::value
>::type>
_LIBCPP_INLINE_VISIBILITY
void __construct_forward_with_exception_guarantees(_Alloc&, _Tp* __begin1, _Tp* __end1, _Tp*& __begin2) {
ptrdiff_t _Np = __end1 - __begin1;
if (_Np > 0) {
_VSTD::memcpy(__begin2, __begin1, _Np * sizeof(_Tp));
__begin2 += _Np;
}
}
template <class _Alloc, class _Iter, class _Ptr>
_LIBCPP_INLINE_VISIBILITY
void __construct_range_forward(_Alloc& __a, _Iter __begin1, _Iter __end1, _Ptr& __begin2) {
typedef allocator_traits<_Alloc> _Traits;
for (; __begin1 != __end1; ++__begin1, (void) ++__begin2) {
_Traits::construct(__a, _VSTD::__to_address(__begin2), *__begin1);
}
}
template <class _Alloc, class _Source, class _Dest,
class _RawSource = typename remove_const<_Source>::type,
class _RawDest = typename remove_const<_Dest>::type,
class =
typename enable_if<
is_trivially_copy_constructible<_Dest>::value &&
is_same<_RawSource, _RawDest>::value &&
(__is_default_allocator<_Alloc>::value || !__has_construct<_Alloc, _Dest*, _Source&>::value)
>::type>
_LIBCPP_INLINE_VISIBILITY
void __construct_range_forward(_Alloc&, _Source* __begin1, _Source* __end1, _Dest*& __begin2) {
ptrdiff_t _Np = __end1 - __begin1;
if (_Np > 0) {
_VSTD::memcpy(const_cast<_RawDest*>(__begin2), __begin1, _Np * sizeof(_Dest));
__begin2 += _Np;
}
}
template <class _Alloc, class _Ptr>
_LIBCPP_INLINE_VISIBILITY
void __construct_backward_with_exception_guarantees(_Alloc& __a, _Ptr __begin1, _Ptr __end1, _Ptr& __end2) {
static_assert(__is_cpp17_move_insertable<_Alloc>::value,
"The specified type does not meet the requirements of Cpp17MoveInsertable");
typedef allocator_traits<_Alloc> _Traits;
while (__end1 != __begin1) {
_Traits::construct(__a, _VSTD::__to_address(__end2 - 1),
#ifdef _LIBCPP_NO_EXCEPTIONS
_VSTD::move(*--__end1)
#else
_VSTD::move_if_noexcept(*--__end1)
#endif
);
--__end2;
}
}
template <class _Alloc, class _Tp, class = typename enable_if<
(__is_default_allocator<_Alloc>::value || !__has_construct<_Alloc, _Tp*, _Tp>::value) &&
is_trivially_move_constructible<_Tp>::value
>::type>
_LIBCPP_INLINE_VISIBILITY
void __construct_backward_with_exception_guarantees(_Alloc&, _Tp* __begin1, _Tp* __end1, _Tp*& __end2) {
ptrdiff_t _Np = __end1 - __begin1;
__end2 -= _Np;
if (_Np > 0)
_VSTD::memcpy(__end2, __begin1, _Np * sizeof(_Tp));
}
2010-05-12 03:42:16 +08:00
struct __destruct_n
{
private:
size_t __size_;
2010-05-12 03:42:16 +08:00
template <class _Tp>
_LIBCPP_INLINE_VISIBILITY void __process(_Tp* __p, false_type) _NOEXCEPT
{for (size_t __i = 0; __i < __size_; ++__i, ++__p) __p->~_Tp();}
2010-05-12 03:42:16 +08:00
template <class _Tp>
_LIBCPP_INLINE_VISIBILITY void __process(_Tp*, true_type) _NOEXCEPT
2010-05-12 03:42:16 +08:00
{}
_LIBCPP_INLINE_VISIBILITY void __incr(false_type) _NOEXCEPT
{++__size_;}
_LIBCPP_INLINE_VISIBILITY void __incr(true_type) _NOEXCEPT
2010-05-12 03:42:16 +08:00
{}
_LIBCPP_INLINE_VISIBILITY void __set(size_t __s, false_type) _NOEXCEPT
{__size_ = __s;}
_LIBCPP_INLINE_VISIBILITY void __set(size_t, true_type) _NOEXCEPT
2010-05-12 03:42:16 +08:00
{}
public:
_LIBCPP_INLINE_VISIBILITY explicit __destruct_n(size_t __s) _NOEXCEPT
: __size_(__s) {}
2010-05-12 03:42:16 +08:00
template <class _Tp>
_LIBCPP_INLINE_VISIBILITY void __incr() _NOEXCEPT
{__incr(integral_constant<bool, is_trivially_destructible<_Tp>::value>());}
2010-05-12 03:42:16 +08:00
template <class _Tp>
_LIBCPP_INLINE_VISIBILITY void __set(size_t __s, _Tp*) _NOEXCEPT
{__set(__s, integral_constant<bool, is_trivially_destructible<_Tp>::value>());}
2010-05-12 03:42:16 +08:00
template <class _Tp>
_LIBCPP_INLINE_VISIBILITY void operator()(_Tp* __p) _NOEXCEPT
{__process(__p, integral_constant<bool, is_trivially_destructible<_Tp>::value>());}
2010-05-12 03:42:16 +08:00
};
_LIBCPP_FUNC_VIS void* align(size_t __align, size_t __sz, void*& __ptr, size_t& __space);
2010-05-12 03:42:16 +08:00
// --- Helper for container swap --
template <typename _Alloc>
_LIBCPP_INLINE_VISIBILITY
void __swap_allocator(_Alloc & __a1, _Alloc & __a2, true_type)
#if _LIBCPP_STD_VER >= 14
_NOEXCEPT
#else
_NOEXCEPT_(__is_nothrow_swappable<_Alloc>::value)
#endif
{
using _VSTD::swap;
swap(__a1, __a2);
}
template <typename _Alloc>
inline _LIBCPP_INLINE_VISIBILITY
void __swap_allocator(_Alloc &, _Alloc &, false_type) _NOEXCEPT {}
template <typename _Alloc>
inline _LIBCPP_INLINE_VISIBILITY
void __swap_allocator(_Alloc & __a1, _Alloc & __a2)
#if _LIBCPP_STD_VER >= 14
_NOEXCEPT
#else
_NOEXCEPT_(__is_nothrow_swappable<_Alloc>::value)
#endif
{
_VSTD::__swap_allocator(__a1, __a2,
integral_constant<bool, allocator_traits<_Alloc>::propagate_on_container_swap::value>());
}
template <typename _Alloc, typename _Traits=allocator_traits<_Alloc> >
struct __noexcept_move_assign_container : public integral_constant<bool,
_Traits::propagate_on_container_move_assignment::value
#if _LIBCPP_STD_VER > 14
|| _Traits::is_always_equal::value
#else
&& is_nothrow_move_assignable<_Alloc>::value
#endif
> {};
template <class _Tp, class _Alloc>
struct __temp_value {
typedef allocator_traits<_Alloc> _Traits;
typename aligned_storage<sizeof(_Tp), _LIBCPP_ALIGNOF(_Tp)>::type __v;
_Alloc &__a;
_Tp *__addr() { return reinterpret_cast<_Tp *>(addressof(__v)); }
_Tp & get() { return *__addr(); }
template<class... _Args>
_LIBCPP_NO_CFI
__temp_value(_Alloc &__alloc, _Args&& ... __args) : __a(__alloc) {
_Traits::construct(__a, reinterpret_cast<_Tp*>(addressof(__v)),
_VSTD::forward<_Args>(__args)...);
}
~__temp_value() { _Traits::destroy(__a, __addr()); }
};
template<typename _Alloc, typename = void, typename = void>
struct __is_allocator : false_type {};
template<typename _Alloc>
struct __is_allocator<_Alloc,
typename __void_t<typename _Alloc::value_type>::type,
typename __void_t<decltype(declval<_Alloc&>().allocate(size_t(0)))>::type
>
: true_type {};
// __builtin_new_allocator -- A non-templated helper for allocating and
// deallocating memory using __builtin_operator_new and
// __builtin_operator_delete. It should be used in preference to
// `std::allocator<T>` to avoid additional instantiations.
struct __builtin_new_allocator {
struct __builtin_new_deleter {
typedef void* pointer_type;
_LIBCPP_CONSTEXPR explicit __builtin_new_deleter(size_t __size, size_t __align)
: __size_(__size), __align_(__align) {}
void operator()(void* p) const _NOEXCEPT {
_VSTD::__libcpp_deallocate(p, __size_, __align_);
}
private:
size_t __size_;
size_t __align_;
};
typedef unique_ptr<void, __builtin_new_deleter> __holder_t;
static __holder_t __allocate_bytes(size_t __s, size_t __align) {
return __holder_t(_VSTD::__libcpp_allocate(__s, __align),
__builtin_new_deleter(__s, __align));
}
static void __deallocate_bytes(void* __p, size_t __s,
size_t __align) _NOEXCEPT {
_VSTD::__libcpp_deallocate(__p, __s, __align);
}
template <class _Tp>
_LIBCPP_NODEBUG _LIBCPP_ALWAYS_INLINE
static __holder_t __allocate_type(size_t __n) {
return __allocate_bytes(__n * sizeof(_Tp), _LIBCPP_ALIGNOF(_Tp));
}
template <class _Tp>
_LIBCPP_NODEBUG _LIBCPP_ALWAYS_INLINE
static void __deallocate_type(void* __p, size_t __n) _NOEXCEPT {
__deallocate_bytes(__p, __n * sizeof(_Tp), _LIBCPP_ALIGNOF(_Tp));
}
};
2010-05-12 03:42:16 +08:00
_LIBCPP_END_NAMESPACE_STD
_LIBCPP_POP_MACROS
#if defined(_LIBCPP_HAS_PARALLEL_ALGORITHMS) && _LIBCPP_STD_VER >= 17
# include <__pstl_memory>
#endif
#endif // _LIBCPP_MEMORY