llvm-project/libcxx/include/memory

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

1034 lines
38 KiB
Plaintext
Raw Normal View History

2010-05-12 03:42:16 +08:00
// -*- C++ -*-
//===----------------------------------------------------------------------===//
2010-05-12 03:42:16 +08:00
//
// 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 Pointer>
struct allocation_result {
Pointer ptr;
size_t count;
}; // since C++23
template<class Allocator>
[[nodiscard]] constexpr allocation_result<typename allocator_traits<Allocator>::pointer>
allocate_at_least(Allocator& a, size_t n); // since C++23
2010-05-12 03:42:16 +08:00
template <>
class allocator<void> // 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 // deprecated in C++17, removed in C++20
: public iterator<output_iterator_tag, void, void, void, void> // until C++17
2010-05-12 03:42:16 +08:00
{
public:
typedef output_iterator_tag iterator_category;
typedef void value_type;
typedef void difference_type; // until C++20
typedef ptrdiff_t difference_type; // since C++20
typedef void pointer;
typedef void reference;
2010-05-12 03:42:16 +08:00
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);
namespace ranges {
template<class InputIterator, class OutputIterator>
using uninitialized_copy_result = in_out_result<InputIterator, OutputIterator>; // since C++20
template<input_iterator InputIterator, sentinel-for<InputIterator> Sentinel1, nothrow-forward-iterator OutputIterator, nothrow-sentinel-for<OutputIterator> Sentinel2>
requires constructible_from<iter_value_t<OutputIterator>, iter_reference_t<InputIterator>>
uninitialized_copy_result<InputIterator, OutputIterator>
uninitialized_copy(InputIterator ifirst, Sentinel1 ilast, OutputIterator ofirst, Sentinel2 olast); // since C++20
template<input_range InputRange, nothrow-forward-range OutputRange>
requires constructible_from<range_value_t<OutputRange>, range_reference_t<InputRange>>
uninitialized_copy_result<borrowed_iterator_t<InputRange>, borrowed_iterator_t<OutputRange>>
uninitialized_copy(InputRange&& in_range, OutputRange&& out_range); // since C++20
}
template <class InputIterator, class Size, class ForwardIterator>
ForwardIterator
uninitialized_copy_n(InputIterator first, Size n, ForwardIterator result);
namespace ranges {
template<class InputIterator, class OutputIterator>
using uninitialized_copy_n_result = in_out_result<InputIterator, OutputIterator>; // since C++20
template<input_iterator InputIterator, nothrow-forward-iterator OutputIterator, nothrow-sentinel-for<OutputIterator> Sentinel>
requires constructible_from<iter_value_t<OutputIterator>, iter_reference_t<InputIterator>>
uninitialized_copy_n_result<InputIterator, OutputIterator>
uninitialized_copy_n(InputIterator ifirst, iter_difference_t<InputIterator> n, OutputIterator ofirst, Sentinel olast); // since C++20
}
2010-05-12 03:42:16 +08:00
template <class ForwardIterator, class T>
void uninitialized_fill(ForwardIterator first, ForwardIterator last, const T& x);
namespace ranges {
template <nothrow-forward-iterator ForwardIterator, nothrow-sentinel-for<ForwardIterator> Sentinel, class T>
requires constructible_from<iter_value_t<ForwardIterator>, const T&>
ForwardIterator uninitialized_fill(ForwardIterator first, Sentinel last, const T& x); // since C++20
template <nothrow-forward-range ForwardRange, class T>
requires constructible_from<range_value_t<ForwardRange>, const T&>
borrowed_iterator_t<ForwardRange> uninitialized_fill(ForwardRange&& range, const T& x); // since C++20
}
2010-05-12 03:42:16 +08:00
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
namespace ranges {
template <nothrow-forward-iterator ForwardIterator, class T>
requires constructible_from<iter_value_t<ForwardIterator>, const T&>
ForwardIterator uninitialized_fill_n(ForwardIterator first, iter_difference_t<ForwardIterator> n); // since C++20
}
template <class T, class ...Args>
constexpr T* construct_at(T* location, Args&& ...args); // since C++20
namespace ranges {
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
namespace ranges {
template<destructible T>
constexpr void destroy_at(T* location) noexcept; // since C++20
}
template <class ForwardIterator>
void destroy(ForwardIterator first, ForwardIterator last); // constexpr in C++20
namespace ranges {
template<nothrow-input-iterator InputIterator, nothrow-sentinel-for<InputIterator> Sentinel>
requires destructible<iter_value_t<InputIterator>>
constexpr InputIterator destroy(InputIterator first, Sentinel last) noexcept; // since C++20
template<nothrow-input-range InputRange>
requires destructible<range_value_t<InputRange>>
constexpr borrowed_iterator_t<InputRange> destroy(InputRange&& range) noexcept; // since C++20
}
template <class ForwardIterator, class Size>
ForwardIterator destroy_n(ForwardIterator first, Size n); // constexpr in C++20
namespace ranges {
template<nothrow-input-iterator InputIterator>
requires destructible<iter_value_t<InputIterator>>
constexpr InputIterator destroy_n(InputIterator first, iter_difference_t<InputIterator> n) noexcept; // since C++20
}
template <class InputIterator, class ForwardIterator>
ForwardIterator uninitialized_move(InputIterator first, InputIterator last, ForwardIterator result);
namespace ranges {
template<class InputIterator, class OutputIterator>
using uninitialized_move_result = in_out_result<InputIterator, OutputIterator>; // since C++20
template <input_iterator InputIterator, sentinel_for<InputIterator> Sentinel1, nothrow-forward-iterator OutputIterator, nothrow-sentinel-for<O> Sentinel2>
requires constructible_from<iter_value_t<OutputIterator>, iter_rvalue_reference_t<InputIterator>>
uninitialized_move_result<InputIterator, OutputIterator>
uninitialized_move(InputIterator ifirst, Sentinel1 ilast, OutputIterator ofirst, Sentinel2 olast); // since C++20
template<input_range InputRange, nothrow-forward-range OutputRange>
requires constructible_from<range_value_t<OutputRange>, range_rvalue_reference_t<InputRange>>
uninitialized_move_result<borrowed_iterator_t<InputRange>, borrowed_iterator_t<OutputRange>>
uninitialized_move(InputRange&& in_range, OutputRange&& out_range); // since C++20
}
template <class InputIterator, class Size, class ForwardIterator>
pair<InputIterator,ForwardIterator> uninitialized_move_n(InputIterator first, Size n, ForwardIterator result);
namespace ranges {
template<class InputIterator, class OutputIterator>
using uninitialized_move_n_result = in_out_result<InputIterator, OutputIterator>; // since C++20
template<input_iterator InputIterator, nothrow-forward-iterator OutputIterator, nothrow-sentinel-for<OutputIterator> Sentinel>
requires constructible_from<iter_value_t<OutputIterator>, iter_rvalue_reference_t<InputIterator>>
uninitialized_move_n_result<InputIterator, OutputIterator>
uninitialized_move_n(InputIterator ifirst, iter_difference_t<InputIterator> n, OutputIterator ofirst, Sentinel olast); // since C++20
}
template <class ForwardIterator>
void uninitialized_value_construct(ForwardIterator first, ForwardIterator last);
namespace ranges {
template <nothrow-forward-iterator ForwardIterator, nothrow-sentinel-for<ForwardIterator> Sentinel>
requires default_initializable<iter_value_t<ForwardIterator>>
ForwardIterator uninitialized_value_construct(ForwardIterator first, Sentinel last); // since C++20
template <nothrow-forward-range ForwardRange>
requires default_initializable<range_value_t<ForwardRange>>
borrowed_iterator_t<ForwardRange> uninitialized_value_construct(ForwardRange&& r); // since C++20
}
template <class ForwardIterator, class Size>
ForwardIterator uninitialized_value_construct_n(ForwardIterator first, Size n);
namespace ranges {
template <nothrow-forward-iterator ForwardIterator>
requires default_initializable<iter_value_t<ForwardIterator>>
ForwardIterator uninitialized_value_construct_n(ForwardIterator first, iter_difference_t<ForwardIterator> n); // since C++20
}
template <class ForwardIterator>
void uninitialized_default_construct(ForwardIterator first, ForwardIterator last);
namespace ranges {
template <nothrow-forward-iterator ForwardIterator, nothrow-sentinel-for<ForwardIterator> Sentinel>
requires default_initializable<iter_value_t<ForwardIterator>>
ForwardIterator uninitialized_default_construct(ForwardIterator first, Sentinel last); // since C++20
template <nothrow-forward-range ForwardRange>
requires default_initializable<range_value_t<ForwardRange>>
borrowed_iterator_t<ForwardRange> uninitialized_default_construct(ForwardRange&& r); // since C++20
}
template <class ForwardIterator, class Size>
ForwardIterator uninitialized_default_construct_n(ForwardIterator first, Size n);
namespace ranges {
template <nothrow-forward-iterator ForwardIterator>
requires default_initializable<iter_value_t<ForwardIterator>>
ForwardIterator uninitialized_default_construct_n(ForwardIterator first, iter_difference_t<ForwardIterator> n); // since C++20
}
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; // until C++17
typedef remove_extent_t<T> element_type; // since C++17
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); // T is not an array
2010-08-20 02:39:17 +08:00
template<class T, class A, class... Args>
shared_ptr<T> allocate_shared(const A& a, Args&&... args); // T is not an array
template<class T>
shared_ptr<T> make_shared(size_t N); // T is U[] (since C++20)
template<class T, class A>
shared_ptr<T> allocate_shared(const A& a, size_t N); // T is U[] (since C++20)
template<class T>
shared_ptr<T> make_shared(); // T is U[N] (since C++20)
template<class T, class A>
shared_ptr<T> allocate_shared(const A& a); // T is U[N] (since C++20)
template<class T>
shared_ptr<T> make_shared(size_t N, const remove_extent_t<T>& u); // T is U[] (since C++20)
template<class T, class A>
shared_ptr<T> allocate_shared(const A& a, size_t N, const remove_extent_t<T>& u); // T is U[] (since C++20)
template<class T> shared_ptr<T>
make_shared(const remove_extent_t<T>& u); // T is U[N] (since C++20)
template<class T, class A>
shared_ptr<T> allocate_shared(const A& a, const remove_extent_t<T>& u); // T is U[N] (since C++20)
2010-08-20 02:39:17 +08:00
template<class T>
class weak_ptr
{
public:
typedef T element_type; // until C++17
typedef remove_extent_t<T> element_type; // since C++17
2010-08-20 02:39:17 +08:00
// 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;
// [ptr.align]
2010-05-12 03:42:16 +08:00
void* align(size_t alignment, size_t size, void*& ptr, size_t& space);
template<size_t N, class T>
[[nodiscard]] constexpr T* assume_aligned(T* ptr); // since C++20
2010-05-12 03:42:16 +08:00
} // std
*/
#include <__algorithm/copy.h>
#include <__algorithm/move.h>
#include <__assert> // all public C++ headers provide the assertion handler
2010-05-12 03:42:16 +08:00
#include <__config>
#include <__memory/addressof.h>
#include <__memory/allocate_at_least.h>
#include <__memory/allocation_guard.h>
#include <__memory/allocator.h>
#include <__memory/allocator_arg_t.h>
#include <__memory/allocator_traits.h>
#include <__memory/assume_aligned.h>
#include <__memory/auto_ptr.h>
#include <__memory/compressed_pair.h>
#include <__memory/concepts.h>
#include <__memory/construct_at.h>
#include <__memory/pointer_traits.h>
#include <__memory/ranges_construct_at.h>
#include <__memory/ranges_uninitialized_algorithms.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 <__memory/uses_allocator.h>
#include <cstddef>
#include <cstdint>
#include <cstring>
#include <iosfwd>
#include <new>
#include <stdexcept>
#include <tuple>
#include <type_traits>
#include <typeinfo>
#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
[libc++] Re-add transitive includes that had been removed since LLVM 14 This commit re-adds transitive includes that had been removed by 4cd04d1687f1, c36870c8e79c, a83f4b9cda57, 1458458b558d, 2e2f3158c604, and 489637e66dd3. This should cover almost all the includes that had been removed since LLVM 14 and that would contribute to breaking user code when releasing LLVM 15. It is possible to disable the inclusion of these headers by defining _LIBCPP_REMOVE_TRANSITIVE_INCLUDES. The intent is that vendors will enable that macro and start fixing downstream issues immediately. We can then remove the macro (and the transitive includes) by default in a future release. That way, we will break users only once by removing transitive includes in bulk instead of doing it bit by bit a every release, which is more disruptive for users. Note 1: The set of headers to re-add was found by re-generating the transitive include test on a checkout of release/14.x, which provided the list of all transitive includes we used to provide. Note 2: Several includes of <vector>, <optional>, <array> and <unordered_map> have been added in this commit. These transitive inclusions were added when we implemented boyer_moore_searcher in <functional>. Note 3: This is a best effort patch to try and resolve downstream breakage caused since branching LLVM 14. I wasn't able to perfectly mirror transitive includes in LLVM 14 for a few headers, so I added a release note explaining it. To summarize, adding boyer_moore_searcher created a bunch of circular dependencies, so we have to break backwards compatibility in a few cases. Differential Revision: https://reviews.llvm.org/D128661
2022-06-28 03:53:41 +08:00
#ifndef _LIBCPP_REMOVE_TRANSITIVE_INCLUDES
# include <iterator>
# include <utility>
#endif
// standard-mandated includes
#include <compare>
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header
#endif
2010-05-12 03:42:16 +08:00
_LIBCPP_BEGIN_NAMESPACE_STD
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
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;
#ifdef _LIBCPP_CXX03_LANG
typename aligned_storage<sizeof(_Tp), _LIBCPP_ALIGNOF(_Tp)>::type __v;
#else
union { _Tp __v; };
#endif
_Alloc &__a;
_LIBCPP_CONSTEXPR_AFTER_CXX17 _Tp *__addr() {
#ifdef _LIBCPP_CXX03_LANG
return reinterpret_cast<_Tp*>(std::addressof(__v));
#else
return std::addressof(__v);
#endif
}
_LIBCPP_CONSTEXPR_AFTER_CXX17 _Tp & get() { return *__addr(); }
template<class... _Args>
_LIBCPP_NO_CFI
_LIBCPP_CONSTEXPR_AFTER_CXX17 __temp_value(_Alloc &__alloc, _Args&& ... __args) : __a(__alloc) {
_Traits::construct(__a, __addr(), std::forward<_Args>(__args)...);
}
_LIBCPP_CONSTEXPR_AFTER_CXX17 ~__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
#if defined(_LIBCPP_HAS_PARALLEL_ALGORITHMS) && _LIBCPP_STD_VER >= 17
# include <__pstl_memory>
#endif
#endif // _LIBCPP_MEMORY