Skip to content

Commit b0386a5

Browse files
committed
First half of C++17's splicing maps and sets
This commit adds a node handle type, (located in __node_handle), and adds extract() and insert() members to all map and set types, as well as their implementations in __tree and __hash_table. The second half of this feature is adding merge() members, which splice nodes in bulk from one container into another. This will be committed in a follow-up. Differential revision: https://reviews.llvm.org/D46845 llvm-svn: 338472
1 parent 9057546 commit b0386a5

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

43 files changed

+3214
-9
lines changed

libcxx/include/CMakeLists.txt

+1
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ set(files
1111
__libcpp_version
1212
__locale
1313
__mutex_base
14+
__node_handle
1415
__nullptr
1516
__split_buffer
1617
__sso_allocator

libcxx/include/__hash_table

+120
Original file line numberDiff line numberDiff line change
@@ -859,6 +859,17 @@ public:
859859
template <class> friend class __hash_map_node_destructor;
860860
};
861861

862+
#if _LIBCPP_STD_VER > 14
863+
template <class _NodeType, class _Alloc>
864+
struct __generic_container_node_destructor;
865+
866+
template <class _Tp, class _VoidPtr, class _Alloc>
867+
struct __generic_container_node_destructor<__hash_node<_Tp, _VoidPtr>, _Alloc>
868+
: __hash_node_destructor<_Alloc>
869+
{
870+
using __hash_node_destructor<_Alloc>::__hash_node_destructor;
871+
};
872+
#endif
862873

863874
#ifndef _LIBCPP_CXX03_LANG
864875
template <class _Key, class _Hash, class _Equal, class _Alloc>
@@ -1151,6 +1162,30 @@ public:
11511162
return __emplace_unique_key_args(_NodeTypes::__get_key(__x), __x);
11521163
}
11531164

1165+
#if _LIBCPP_STD_VER > 14
1166+
template <class _NodeHandle, class _InsertReturnType>
1167+
_LIBCPP_INLINE_VISIBILITY
1168+
_InsertReturnType __node_handle_insert_unique(_NodeHandle&& __nh);
1169+
template <class _NodeHandle>
1170+
_LIBCPP_INLINE_VISIBILITY
1171+
iterator __node_handle_insert_unique(const_iterator __hint,
1172+
_NodeHandle&& __nh);
1173+
1174+
template <class _NodeHandle>
1175+
_LIBCPP_INLINE_VISIBILITY
1176+
iterator __node_handle_insert_multi(_NodeHandle&& __nh);
1177+
template <class _NodeHandle>
1178+
_LIBCPP_INLINE_VISIBILITY
1179+
iterator __node_handle_insert_multi(const_iterator __hint, _NodeHandle&& __nh);
1180+
1181+
template <class _NodeHandle>
1182+
_LIBCPP_INLINE_VISIBILITY
1183+
_NodeHandle __node_handle_extract(key_type const& __key);
1184+
template <class _NodeHandle>
1185+
_LIBCPP_INLINE_VISIBILITY
1186+
_NodeHandle __node_handle_extract(const_iterator __it);
1187+
#endif
1188+
11541189
void clear() _NOEXCEPT;
11551190
void rehash(size_type __n);
11561191
_LIBCPP_INLINE_VISIBILITY void reserve(size_type __n)
@@ -2126,6 +2161,91 @@ __hash_table<_Tp, _Hash, _Equal, _Alloc>::__insert_multi(const_iterator __p,
21262161

21272162
#endif // _LIBCPP_CXX03_LANG
21282163

2164+
#if _LIBCPP_STD_VER > 14
2165+
template <class _Tp, class _Hash, class _Equal, class _Alloc>
2166+
template <class _NodeHandle, class _InsertReturnType>
2167+
_LIBCPP_INLINE_VISIBILITY
2168+
_InsertReturnType
2169+
__hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_handle_insert_unique(
2170+
_NodeHandle&& __nh)
2171+
{
2172+
if (__nh.empty())
2173+
return _InsertReturnType{end(), false, _NodeHandle()};
2174+
pair<iterator, bool> __result = __node_insert_unique(__nh.__ptr_);
2175+
if (__result.second)
2176+
__nh.__release();
2177+
return _InsertReturnType{__result.first, __result.second, _VSTD::move(__nh)};
2178+
}
2179+
2180+
template <class _Tp, class _Hash, class _Equal, class _Alloc>
2181+
template <class _NodeHandle>
2182+
_LIBCPP_INLINE_VISIBILITY
2183+
typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator
2184+
__hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_handle_insert_unique(
2185+
const_iterator, _NodeHandle&& __nh)
2186+
{
2187+
if (__nh.empty())
2188+
return end();
2189+
pair<iterator, bool> __result = __node_insert_unique(__nh.__ptr_);
2190+
if (__result.second)
2191+
__nh.__release();
2192+
return __result.first;
2193+
}
2194+
2195+
template <class _Tp, class _Hash, class _Equal, class _Alloc>
2196+
template <class _NodeHandle>
2197+
_LIBCPP_INLINE_VISIBILITY
2198+
_NodeHandle
2199+
__hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_handle_extract(
2200+
key_type const& __key)
2201+
{
2202+
iterator __i = find(__key);
2203+
if (__i == end())
2204+
return _NodeHandle();
2205+
return __node_handle_extract<_NodeHandle>(__i);
2206+
}
2207+
2208+
template <class _Tp, class _Hash, class _Equal, class _Alloc>
2209+
template <class _NodeHandle>
2210+
_LIBCPP_INLINE_VISIBILITY
2211+
_NodeHandle
2212+
__hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_handle_extract(
2213+
const_iterator __p)
2214+
{
2215+
allocator_type __alloc(__node_alloc());
2216+
return _NodeHandle(remove(__p).release(), __alloc);
2217+
}
2218+
2219+
template <class _Tp, class _Hash, class _Equal, class _Alloc>
2220+
template <class _NodeHandle>
2221+
_LIBCPP_INLINE_VISIBILITY
2222+
typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator
2223+
__hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_handle_insert_multi(
2224+
_NodeHandle&& __nh)
2225+
{
2226+
if (__nh.empty())
2227+
return end();
2228+
iterator __result = __node_insert_multi(__nh.__ptr_);
2229+
__nh.__release();
2230+
return __result;
2231+
}
2232+
2233+
template <class _Tp, class _Hash, class _Equal, class _Alloc>
2234+
template <class _NodeHandle>
2235+
_LIBCPP_INLINE_VISIBILITY
2236+
typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator
2237+
__hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_handle_insert_multi(
2238+
const_iterator __hint, _NodeHandle&& __nh)
2239+
{
2240+
if (__nh.empty())
2241+
return end();
2242+
iterator __result = __node_insert_multi(__hint, __nh.__ptr_);
2243+
__nh.__release();
2244+
return __result;
2245+
}
2246+
2247+
#endif // _LIBCPP_STD_VER > 14
2248+
21292249
template <class _Tp, class _Hash, class _Equal, class _Alloc>
21302250
void
21312251
__hash_table<_Tp, _Hash, _Equal, _Alloc>::rehash(size_type __n)

libcxx/include/__node_handle

+212
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,212 @@
1+
// -*- C++ -*-
2+
//===----------------------------------------------------------------------===//
3+
//
4+
// The LLVM Compiler Infrastructure
5+
//
6+
// This file is dual licensed under the MIT and the University of Illinois Open
7+
// Source Licenses. See LICENSE.TXT for details.
8+
//
9+
//===----------------------------------------------------------------------===//
10+
11+
#ifndef _LIBCPP___NODE_HANDLE
12+
#define _LIBCPP___NODE_HANDLE
13+
14+
#include <__config>
15+
#include <memory>
16+
#include <optional>
17+
18+
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
19+
#pragma GCC system_header
20+
#endif
21+
22+
_LIBCPP_PUSH_MACROS
23+
#include <__undef_macros>
24+
25+
_LIBCPP_BEGIN_NAMESPACE_STD
26+
27+
#if _LIBCPP_STD_VER > 14
28+
29+
#define __cpp_lib_node_extract 201606L
30+
31+
// Specialized in __tree & __hash_table for their _NodeType.
32+
template <class _NodeType, class _Alloc>
33+
struct __generic_container_node_destructor;
34+
35+
template <class _NodeType, class _Alloc,
36+
template <class, class> class _MapOrSetSpecifics>
37+
class _LIBCPP_TEMPLATE_VIS __basic_node_handle
38+
: public _MapOrSetSpecifics<
39+
_NodeType,
40+
__basic_node_handle<_NodeType, _Alloc, _MapOrSetSpecifics>>
41+
{
42+
template <class _Tp, class _Compare, class _Allocator>
43+
friend class __tree;
44+
template <class _Tp, class _Hash, class _Equal, class _Allocator>
45+
friend class __hash_table;
46+
friend struct _MapOrSetSpecifics<
47+
_NodeType, __basic_node_handle<_NodeType, _Alloc, _MapOrSetSpecifics>>;
48+
49+
typedef allocator_traits<_Alloc> __alloc_traits;
50+
typedef typename __rebind_pointer<typename __alloc_traits::void_pointer,
51+
_NodeType>::type
52+
__node_pointer_type;
53+
54+
public:
55+
typedef _Alloc allocator_type;
56+
57+
private:
58+
__node_pointer_type __ptr_ = nullptr;
59+
optional<allocator_type> __alloc_;
60+
61+
_LIBCPP_INLINE_VISIBILITY
62+
void __release()
63+
{
64+
__ptr_ = nullptr;
65+
__alloc_ = _VSTD::nullopt;
66+
}
67+
68+
_LIBCPP_INLINE_VISIBILITY
69+
void __destroy_node_pointer()
70+
{
71+
if (__ptr_ != nullptr)
72+
{
73+
typedef typename __allocator_traits_rebind<
74+
allocator_type, _NodeType>::type __node_alloc_type;
75+
__node_alloc_type __alloc(*__alloc_);
76+
__generic_container_node_destructor<_NodeType, __node_alloc_type>(
77+
__alloc, true)(__ptr_);
78+
__ptr_ = nullptr;
79+
}
80+
}
81+
82+
_LIBCPP_INLINE_VISIBILITY
83+
__basic_node_handle(__node_pointer_type __ptr,
84+
allocator_type const& __alloc)
85+
: __ptr_(__ptr), __alloc_(__alloc)
86+
{
87+
}
88+
89+
public:
90+
_LIBCPP_INLINE_VISIBILITY
91+
__basic_node_handle() = default;
92+
93+
_LIBCPP_INLINE_VISIBILITY
94+
__basic_node_handle(__basic_node_handle&& __other) noexcept
95+
: __ptr_(__other.__ptr_),
96+
__alloc_(_VSTD::move(__other.__alloc_))
97+
{
98+
__other.__ptr_ = nullptr;
99+
__other.__alloc_ = _VSTD::nullopt;
100+
}
101+
102+
_LIBCPP_INLINE_VISIBILITY
103+
__basic_node_handle& operator=(__basic_node_handle&& __other)
104+
{
105+
_LIBCPP_ASSERT(
106+
__alloc_ == _VSTD::nullopt ||
107+
__alloc_traits::propagate_on_container_move_assignment::value ||
108+
__alloc_ == __other.__alloc_,
109+
"node_type with incompatible allocator passed to "
110+
"node_type::operator=(node_type&&)");
111+
112+
__destroy_node_pointer();
113+
__ptr_ = __other.__ptr_;
114+
115+
if (__alloc_traits::propagate_on_container_move_assignment::value ||
116+
__alloc_ == _VSTD::nullopt)
117+
__alloc_ = _VSTD::move(__other.__alloc_);
118+
119+
__other.__ptr_ = nullptr;
120+
__other.__alloc_ = _VSTD::nullopt;
121+
122+
return *this;
123+
}
124+
125+
_LIBCPP_INLINE_VISIBILITY
126+
allocator_type get_allocator() const { return *__alloc_; }
127+
128+
_LIBCPP_INLINE_VISIBILITY
129+
explicit operator bool() const { return __ptr_ != nullptr; }
130+
131+
_LIBCPP_NODISCARD_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY
132+
bool empty() const { return __ptr_ == nullptr; }
133+
134+
_LIBCPP_INLINE_VISIBILITY
135+
void swap(__basic_node_handle& __other) noexcept(
136+
__alloc_traits::propagate_on_container_swap::value ||
137+
__alloc_traits::is_always_equal::value)
138+
{
139+
using _VSTD::swap;
140+
swap(__ptr_, __other.__ptr_);
141+
if (__alloc_traits::propagate_on_container_swap::value ||
142+
__alloc_ == _VSTD::nullopt || __other.__alloc_ == _VSTD::nullopt)
143+
swap(__alloc_, __other.__alloc_);
144+
}
145+
146+
_LIBCPP_INLINE_VISIBILITY
147+
friend void swap(__basic_node_handle& __a, __basic_node_handle& __b)
148+
noexcept(noexcept(__a.swap(__b))) { __a.swap(__b); }
149+
150+
_LIBCPP_INLINE_VISIBILITY
151+
~__basic_node_handle()
152+
{
153+
__destroy_node_pointer();
154+
}
155+
};
156+
157+
template <class _NodeType, class _Derived>
158+
struct __set_node_handle_specifics
159+
{
160+
typedef typename _NodeType::__node_value_type value_type;
161+
162+
_LIBCPP_INLINE_VISIBILITY
163+
value_type& value() const
164+
{
165+
return static_cast<_Derived const*>(this)->__ptr_->__value_;
166+
}
167+
};
168+
169+
template <class _NodeType, class _Derived>
170+
struct __map_node_handle_specifics
171+
{
172+
typedef typename _NodeType::__node_value_type::key_type key_type;
173+
typedef typename _NodeType::__node_value_type::mapped_type mapped_type;
174+
175+
_LIBCPP_INLINE_VISIBILITY
176+
key_type& key() const
177+
{
178+
return static_cast<_Derived const*>(this)->
179+
__ptr_->__value_.__ref().first;
180+
}
181+
182+
_LIBCPP_INLINE_VISIBILITY
183+
mapped_type& mapped() const
184+
{
185+
return static_cast<_Derived const*>(this)->
186+
__ptr_->__value_.__ref().second;
187+
}
188+
};
189+
190+
template <class _NodeType, class _Alloc>
191+
using __set_node_handle =
192+
__basic_node_handle< _NodeType, _Alloc, __set_node_handle_specifics>;
193+
194+
template <class _NodeType, class _Alloc>
195+
using __map_node_handle =
196+
__basic_node_handle< _NodeType, _Alloc, __map_node_handle_specifics>;
197+
198+
template <class _Iterator, class _NodeType>
199+
_LIBCPP_TEMPLATE_VIS
200+
struct __insert_return_type
201+
{
202+
_Iterator position;
203+
bool inserted;
204+
_NodeType node;
205+
};
206+
207+
#endif // _LIBCPP_STD_VER > 14
208+
209+
_LIBCPP_END_NAMESPACE_STD
210+
_LIBCPP_POP_MACROS
211+
212+
#endif

0 commit comments

Comments
 (0)