1eb8650a7SLouis Dionne //===----------------------------------------------------------------------===//
2f554add5SHoward Hinnant //
357b08b09SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
457b08b09SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
557b08b09SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6f554add5SHoward Hinnant //
7f554add5SHoward Hinnant //===----------------------------------------------------------------------===//
8f554add5SHoward Hinnant
9*f87aa19bSLouis Dionne #include <__assert>
10bbb0f2c7SArthur O'Dwyer #include <__config>
11bbb0f2c7SArthur O'Dwyer #include <__debug>
12bbb0f2c7SArthur O'Dwyer #include <__hash_table>
13bbb0f2c7SArthur O'Dwyer #include <algorithm>
14bbb0f2c7SArthur O'Dwyer #include <cstdio>
15bbb0f2c7SArthur O'Dwyer #include <functional>
16bbb0f2c7SArthur O'Dwyer #include <string>
17bbb0f2c7SArthur O'Dwyer
18996e62eeSPetr Hosek #ifndef _LIBCPP_HAS_NO_THREADS
19bbb0f2c7SArthur O'Dwyer # include <mutex>
20a9b5fff5SMichał Górny # if defined(__ELF__) && defined(_LIBCPP_LINK_PTHREAD_LIB)
21996e62eeSPetr Hosek # pragma comment(lib, "pthread")
22996e62eeSPetr Hosek # endif
23996e62eeSPetr Hosek #endif
24f554add5SHoward Hinnant
25f554add5SHoward Hinnant _LIBCPP_BEGIN_NAMESPACE_STD
26f554add5SHoward Hinnant
276e41256fSHoward Hinnant _LIBCPP_FUNC_VIS
28f554add5SHoward Hinnant __libcpp_db*
__get_db()29f554add5SHoward Hinnant __get_db()
30f554add5SHoward Hinnant {
3181875a67SLouis Dionne static _LIBCPP_NO_DESTROY __libcpp_db db;
32f554add5SHoward Hinnant return &db;
33267e3e1eSHoward Hinnant }
34f554add5SHoward Hinnant
356e41256fSHoward Hinnant _LIBCPP_FUNC_VIS
36f554add5SHoward Hinnant const __libcpp_db*
__get_const_db()37f554add5SHoward Hinnant __get_const_db()
38f554add5SHoward Hinnant {
39f554add5SHoward Hinnant return __get_db();
40f554add5SHoward Hinnant }
41f554add5SHoward Hinnant
42f554add5SHoward Hinnant namespace
43f554add5SHoward Hinnant {
44f554add5SHoward Hinnant
45b3fcc67fSJonathan Roelofs #ifndef _LIBCPP_HAS_NO_THREADS
46f554add5SHoward Hinnant typedef mutex mutex_type;
47f554add5SHoward Hinnant typedef lock_guard<mutex_type> WLock;
48f554add5SHoward Hinnant typedef lock_guard<mutex_type> RLock;
49f554add5SHoward Hinnant
50f554add5SHoward Hinnant mutex_type&
mut()51f554add5SHoward Hinnant mut()
52f554add5SHoward Hinnant {
5381875a67SLouis Dionne static _LIBCPP_NO_DESTROY mutex_type m;
54f554add5SHoward Hinnant return m;
55f554add5SHoward Hinnant }
56b3fcc67fSJonathan Roelofs #endif // !_LIBCPP_HAS_NO_THREADS
57f554add5SHoward Hinnant
58f554add5SHoward Hinnant } // unnamed namespace
59f554add5SHoward Hinnant
~__i_node()60f554add5SHoward Hinnant __i_node::~__i_node()
61f554add5SHoward Hinnant {
62f554add5SHoward Hinnant if (__next_)
63f554add5SHoward Hinnant {
64f554add5SHoward Hinnant __next_->~__i_node();
65f554add5SHoward Hinnant free(__next_);
66f554add5SHoward Hinnant }
67f554add5SHoward Hinnant }
68f554add5SHoward Hinnant
~__c_node()69f554add5SHoward Hinnant __c_node::~__c_node()
70f554add5SHoward Hinnant {
71f554add5SHoward Hinnant free(beg_);
72f554add5SHoward Hinnant if (__next_)
73f554add5SHoward Hinnant {
74f554add5SHoward Hinnant __next_->~__c_node();
75f554add5SHoward Hinnant free(__next_);
76f554add5SHoward Hinnant }
77f554add5SHoward Hinnant }
78f554add5SHoward Hinnant
__libcpp_db()79f554add5SHoward Hinnant __libcpp_db::__libcpp_db()
80f554add5SHoward Hinnant : __cbeg_(nullptr),
81f554add5SHoward Hinnant __cend_(nullptr),
82f554add5SHoward Hinnant __csz_(0),
83f554add5SHoward Hinnant __ibeg_(nullptr),
84f554add5SHoward Hinnant __iend_(nullptr),
85f554add5SHoward Hinnant __isz_(0)
86f554add5SHoward Hinnant {
87f554add5SHoward Hinnant }
88f554add5SHoward Hinnant
~__libcpp_db()89f554add5SHoward Hinnant __libcpp_db::~__libcpp_db()
90f554add5SHoward Hinnant {
91f554add5SHoward Hinnant if (__cbeg_)
92f554add5SHoward Hinnant {
93f554add5SHoward Hinnant for (__c_node** p = __cbeg_; p != __cend_; ++p)
94f554add5SHoward Hinnant {
95f554add5SHoward Hinnant if (*p != nullptr)
96f554add5SHoward Hinnant {
97f554add5SHoward Hinnant (*p)->~__c_node();
98f554add5SHoward Hinnant free(*p);
99f554add5SHoward Hinnant }
100f554add5SHoward Hinnant }
101f554add5SHoward Hinnant free(__cbeg_);
102f554add5SHoward Hinnant }
103f554add5SHoward Hinnant if (__ibeg_)
104f554add5SHoward Hinnant {
105f554add5SHoward Hinnant for (__i_node** p = __ibeg_; p != __iend_; ++p)
106f554add5SHoward Hinnant {
107f554add5SHoward Hinnant if (*p != nullptr)
108f554add5SHoward Hinnant {
109f554add5SHoward Hinnant (*p)->~__i_node();
110f554add5SHoward Hinnant free(*p);
111f554add5SHoward Hinnant }
112f554add5SHoward Hinnant }
113f554add5SHoward Hinnant free(__ibeg_);
114f554add5SHoward Hinnant }
115f554add5SHoward Hinnant }
116f554add5SHoward Hinnant
117f554add5SHoward Hinnant void*
__find_c_from_i(void * __i) const118f554add5SHoward Hinnant __libcpp_db::__find_c_from_i(void* __i) const
119f554add5SHoward Hinnant {
120b3fcc67fSJonathan Roelofs #ifndef _LIBCPP_HAS_NO_THREADS
121f554add5SHoward Hinnant RLock _(mut());
122b3fcc67fSJonathan Roelofs #endif
123f554add5SHoward Hinnant __i_node* i = __find_iterator(__i);
124f7509231SHoward Hinnant _LIBCPP_ASSERT(i != nullptr, "iterator not found in debug database.");
125c36bfc49SHoward Hinnant return i->__c_ != nullptr ? i->__c_->__c_ : nullptr;
126f554add5SHoward Hinnant }
127f554add5SHoward Hinnant
128f554add5SHoward Hinnant void
__insert_ic(void * __i,const void * __c)129f554add5SHoward Hinnant __libcpp_db::__insert_ic(void* __i, const void* __c)
130f554add5SHoward Hinnant {
131b3fcc67fSJonathan Roelofs #ifndef _LIBCPP_HAS_NO_THREADS
132f554add5SHoward Hinnant WLock _(mut());
133b3fcc67fSJonathan Roelofs #endif
134fc88dbd2SHoward Hinnant if (__cbeg_ == __cend_)
135fc88dbd2SHoward Hinnant return;
136c206366fSHoward Hinnant size_t hc = hash<const void*>()(__c) % static_cast<size_t>(__cend_ - __cbeg_);
137f554add5SHoward Hinnant __c_node* c = __cbeg_[hc];
138fc88dbd2SHoward Hinnant if (c == nullptr)
139fc88dbd2SHoward Hinnant return;
140f554add5SHoward Hinnant while (c->__c_ != __c)
141f554add5SHoward Hinnant {
142f554add5SHoward Hinnant c = c->__next_;
143fc88dbd2SHoward Hinnant if (c == nullptr)
144fc88dbd2SHoward Hinnant return;
145f554add5SHoward Hinnant }
146fc88dbd2SHoward Hinnant __i_node* i = __insert_iterator(__i);
147f554add5SHoward Hinnant c->__add(i);
148f554add5SHoward Hinnant i->__c_ = c;
149f554add5SHoward Hinnant }
150f554add5SHoward Hinnant
1511c014d75SEric Fiselier void
__insert_c(void * __c,__libcpp_db::_InsertConstruct * __fn)1521c014d75SEric Fiselier __libcpp_db::__insert_c(void* __c, __libcpp_db::_InsertConstruct *__fn)
153f554add5SHoward Hinnant {
154b3fcc67fSJonathan Roelofs #ifndef _LIBCPP_HAS_NO_THREADS
155f554add5SHoward Hinnant WLock _(mut());
156b3fcc67fSJonathan Roelofs #endif
157c206366fSHoward Hinnant if (__csz_ + 1 > static_cast<size_t>(__cend_ - __cbeg_))
158f554add5SHoward Hinnant {
159c206366fSHoward Hinnant size_t nc = __next_prime(2*static_cast<size_t>(__cend_ - __cbeg_) + 1);
160cb843f5bSLouis Dionne __c_node** cbeg = static_cast<__c_node**>(calloc(nc, sizeof(__c_node*)));
161f554add5SHoward Hinnant if (cbeg == nullptr)
162d437fa5cSMarshall Clow __throw_bad_alloc();
163d437fa5cSMarshall Clow
164f554add5SHoward Hinnant for (__c_node** p = __cbeg_; p != __cend_; ++p)
165f554add5SHoward Hinnant {
166f554add5SHoward Hinnant __c_node* q = *p;
167f554add5SHoward Hinnant while (q != nullptr)
168f554add5SHoward Hinnant {
169f554add5SHoward Hinnant size_t h = hash<void*>()(q->__c_) % nc;
170f554add5SHoward Hinnant __c_node* r = q->__next_;
171f554add5SHoward Hinnant q->__next_ = cbeg[h];
172f554add5SHoward Hinnant cbeg[h] = q;
173f554add5SHoward Hinnant q = r;
174f554add5SHoward Hinnant }
175f554add5SHoward Hinnant }
176f554add5SHoward Hinnant free(__cbeg_);
177f554add5SHoward Hinnant __cbeg_ = cbeg;
178f554add5SHoward Hinnant __cend_ = __cbeg_ + nc;
179f554add5SHoward Hinnant }
180c206366fSHoward Hinnant size_t hc = hash<void*>()(__c) % static_cast<size_t>(__cend_ - __cbeg_);
181f554add5SHoward Hinnant __c_node* p = __cbeg_[hc];
1821c014d75SEric Fiselier void *buf = malloc(sizeof(__c_node));
1831c014d75SEric Fiselier if (buf == nullptr)
184d437fa5cSMarshall Clow __throw_bad_alloc();
1851c014d75SEric Fiselier __cbeg_[hc] = __fn(buf, __c, p);
186d437fa5cSMarshall Clow
187f554add5SHoward Hinnant ++__csz_;
188f554add5SHoward Hinnant }
189f554add5SHoward Hinnant
190f554add5SHoward Hinnant void
__erase_i(void * __i)191f554add5SHoward Hinnant __libcpp_db::__erase_i(void* __i)
192f554add5SHoward Hinnant {
193b3fcc67fSJonathan Roelofs #ifndef _LIBCPP_HAS_NO_THREADS
194f554add5SHoward Hinnant WLock _(mut());
195b3fcc67fSJonathan Roelofs #endif
196f554add5SHoward Hinnant if (__ibeg_ != __iend_)
197f554add5SHoward Hinnant {
198c206366fSHoward Hinnant size_t hi = hash<void*>()(__i) % static_cast<size_t>(__iend_ - __ibeg_);
199f554add5SHoward Hinnant __i_node* p = __ibeg_[hi];
200f554add5SHoward Hinnant if (p != nullptr)
201f554add5SHoward Hinnant {
202f554add5SHoward Hinnant __i_node* q = nullptr;
203f554add5SHoward Hinnant while (p->__i_ != __i)
204f554add5SHoward Hinnant {
205f554add5SHoward Hinnant q = p;
206f554add5SHoward Hinnant p = p->__next_;
207f554add5SHoward Hinnant if (p == nullptr)
208f554add5SHoward Hinnant return;
209f554add5SHoward Hinnant }
210f554add5SHoward Hinnant if (q == nullptr)
211f554add5SHoward Hinnant __ibeg_[hi] = p->__next_;
212f554add5SHoward Hinnant else
213f554add5SHoward Hinnant q->__next_ = p->__next_;
214f554add5SHoward Hinnant __c_node* c = p->__c_;
215f554add5SHoward Hinnant --__isz_;
216f554add5SHoward Hinnant if (c != nullptr)
217f554add5SHoward Hinnant c->__remove(p);
21861bff619SEric Fiselier free(p);
219f554add5SHoward Hinnant }
220f554add5SHoward Hinnant }
221f554add5SHoward Hinnant }
222f554add5SHoward Hinnant
223f554add5SHoward Hinnant void
__invalidate_all(void * __c)224f554add5SHoward Hinnant __libcpp_db::__invalidate_all(void* __c)
225f554add5SHoward Hinnant {
226b3fcc67fSJonathan Roelofs #ifndef _LIBCPP_HAS_NO_THREADS
227f554add5SHoward Hinnant WLock _(mut());
228b3fcc67fSJonathan Roelofs #endif
229fc88dbd2SHoward Hinnant if (__cend_ != __cbeg_)
230fc88dbd2SHoward Hinnant {
231c206366fSHoward Hinnant size_t hc = hash<void*>()(__c) % static_cast<size_t>(__cend_ - __cbeg_);
232f554add5SHoward Hinnant __c_node* p = __cbeg_[hc];
233fc88dbd2SHoward Hinnant if (p == nullptr)
234fc88dbd2SHoward Hinnant return;
235f554add5SHoward Hinnant while (p->__c_ != __c)
236f554add5SHoward Hinnant {
237f554add5SHoward Hinnant p = p->__next_;
238fc88dbd2SHoward Hinnant if (p == nullptr)
239fc88dbd2SHoward Hinnant return;
240f554add5SHoward Hinnant }
241f554add5SHoward Hinnant while (p->end_ != p->beg_)
242f554add5SHoward Hinnant {
243f554add5SHoward Hinnant --p->end_;
244f554add5SHoward Hinnant (*p->end_)->__c_ = nullptr;
245f554add5SHoward Hinnant }
246f554add5SHoward Hinnant }
247fc88dbd2SHoward Hinnant }
248f554add5SHoward Hinnant
249f554add5SHoward Hinnant __c_node*
__find_c_and_lock(void * __c) const250f554add5SHoward Hinnant __libcpp_db::__find_c_and_lock(void* __c) const
251f554add5SHoward Hinnant {
252b3fcc67fSJonathan Roelofs #ifndef _LIBCPP_HAS_NO_THREADS
253f554add5SHoward Hinnant mut().lock();
254b3fcc67fSJonathan Roelofs #endif
255fc88dbd2SHoward Hinnant if (__cend_ == __cbeg_)
256fc88dbd2SHoward Hinnant {
257b3fcc67fSJonathan Roelofs #ifndef _LIBCPP_HAS_NO_THREADS
258fc88dbd2SHoward Hinnant mut().unlock();
259b3fcc67fSJonathan Roelofs #endif
260fc88dbd2SHoward Hinnant return nullptr;
261fc88dbd2SHoward Hinnant }
262c206366fSHoward Hinnant size_t hc = hash<void*>()(__c) % static_cast<size_t>(__cend_ - __cbeg_);
263f554add5SHoward Hinnant __c_node* p = __cbeg_[hc];
264fc88dbd2SHoward Hinnant if (p == nullptr)
265fc88dbd2SHoward Hinnant {
266b3fcc67fSJonathan Roelofs #ifndef _LIBCPP_HAS_NO_THREADS
267fc88dbd2SHoward Hinnant mut().unlock();
268b3fcc67fSJonathan Roelofs #endif
269fc88dbd2SHoward Hinnant return nullptr;
270fc88dbd2SHoward Hinnant }
271f554add5SHoward Hinnant while (p->__c_ != __c)
272f554add5SHoward Hinnant {
273f554add5SHoward Hinnant p = p->__next_;
274fc88dbd2SHoward Hinnant if (p == nullptr)
275fc88dbd2SHoward Hinnant {
276b3fcc67fSJonathan Roelofs #ifndef _LIBCPP_HAS_NO_THREADS
277fc88dbd2SHoward Hinnant mut().unlock();
278b3fcc67fSJonathan Roelofs #endif
279fc88dbd2SHoward Hinnant return nullptr;
280fc88dbd2SHoward Hinnant }
281f554add5SHoward Hinnant }
282f554add5SHoward Hinnant return p;
283f554add5SHoward Hinnant }
284f554add5SHoward Hinnant
285920b56caSHoward Hinnant __c_node*
__find_c(void * __c) const286920b56caSHoward Hinnant __libcpp_db::__find_c(void* __c) const
287920b56caSHoward Hinnant {
288c206366fSHoward Hinnant size_t hc = hash<void*>()(__c) % static_cast<size_t>(__cend_ - __cbeg_);
289920b56caSHoward Hinnant __c_node* p = __cbeg_[hc];
290920b56caSHoward Hinnant _LIBCPP_ASSERT(p != nullptr, "debug mode internal logic error __find_c A");
291920b56caSHoward Hinnant while (p->__c_ != __c)
292920b56caSHoward Hinnant {
293920b56caSHoward Hinnant p = p->__next_;
294920b56caSHoward Hinnant _LIBCPP_ASSERT(p != nullptr, "debug mode internal logic error __find_c B");
295920b56caSHoward Hinnant }
296920b56caSHoward Hinnant return p;
297920b56caSHoward Hinnant }
298920b56caSHoward Hinnant
299f554add5SHoward Hinnant void
unlock() const300f554add5SHoward Hinnant __libcpp_db::unlock() const
301f554add5SHoward Hinnant {
302b3fcc67fSJonathan Roelofs #ifndef _LIBCPP_HAS_NO_THREADS
303f554add5SHoward Hinnant mut().unlock();
304b3fcc67fSJonathan Roelofs #endif
305f554add5SHoward Hinnant }
306f554add5SHoward Hinnant
307f554add5SHoward Hinnant void
__erase_c(void * __c)308f554add5SHoward Hinnant __libcpp_db::__erase_c(void* __c)
309f554add5SHoward Hinnant {
310b3fcc67fSJonathan Roelofs #ifndef _LIBCPP_HAS_NO_THREADS
311f554add5SHoward Hinnant WLock _(mut());
312b3fcc67fSJonathan Roelofs #endif
313fc88dbd2SHoward Hinnant if (__cend_ != __cbeg_)
314fc88dbd2SHoward Hinnant {
315c206366fSHoward Hinnant size_t hc = hash<void*>()(__c) % static_cast<size_t>(__cend_ - __cbeg_);
316f554add5SHoward Hinnant __c_node* p = __cbeg_[hc];
317fc88dbd2SHoward Hinnant if (p == nullptr)
318fc88dbd2SHoward Hinnant return;
319f554add5SHoward Hinnant __c_node* q = nullptr;
320f554add5SHoward Hinnant _LIBCPP_ASSERT(p != nullptr, "debug mode internal logic error __erase_c A");
321f554add5SHoward Hinnant while (p->__c_ != __c)
322f554add5SHoward Hinnant {
323f554add5SHoward Hinnant q = p;
324f554add5SHoward Hinnant p = p->__next_;
325fc88dbd2SHoward Hinnant if (p == nullptr)
326fc88dbd2SHoward Hinnant return;
327f554add5SHoward Hinnant _LIBCPP_ASSERT(p != nullptr, "debug mode internal logic error __erase_c B");
328f554add5SHoward Hinnant }
329f554add5SHoward Hinnant if (q == nullptr)
330f554add5SHoward Hinnant __cbeg_[hc] = p->__next_;
331f554add5SHoward Hinnant else
332f554add5SHoward Hinnant q->__next_ = p->__next_;
333f554add5SHoward Hinnant while (p->end_ != p->beg_)
334f554add5SHoward Hinnant {
335f554add5SHoward Hinnant --p->end_;
336f554add5SHoward Hinnant (*p->end_)->__c_ = nullptr;
337f554add5SHoward Hinnant }
338f554add5SHoward Hinnant free(p->beg_);
339f554add5SHoward Hinnant free(p);
340f554add5SHoward Hinnant --__csz_;
341f554add5SHoward Hinnant }
342fc88dbd2SHoward Hinnant }
343f554add5SHoward Hinnant
344f554add5SHoward Hinnant void
__iterator_copy(void * __i,const void * __i0)345f554add5SHoward Hinnant __libcpp_db::__iterator_copy(void* __i, const void* __i0)
346f554add5SHoward Hinnant {
347b3fcc67fSJonathan Roelofs #ifndef _LIBCPP_HAS_NO_THREADS
348f554add5SHoward Hinnant WLock _(mut());
349b3fcc67fSJonathan Roelofs #endif
350f554add5SHoward Hinnant __i_node* i = __find_iterator(__i);
351f554add5SHoward Hinnant __i_node* i0 = __find_iterator(__i0);
352f554add5SHoward Hinnant __c_node* c0 = i0 != nullptr ? i0->__c_ : nullptr;
353f7509231SHoward Hinnant if (i == nullptr && i0 != nullptr)
354f554add5SHoward Hinnant i = __insert_iterator(__i);
355f554add5SHoward Hinnant __c_node* c = i != nullptr ? i->__c_ : nullptr;
356f554add5SHoward Hinnant if (c != c0)
357f554add5SHoward Hinnant {
358f554add5SHoward Hinnant if (c != nullptr)
359f554add5SHoward Hinnant c->__remove(i);
360f554add5SHoward Hinnant if (i != nullptr)
361f554add5SHoward Hinnant {
362f554add5SHoward Hinnant i->__c_ = nullptr;
363f554add5SHoward Hinnant if (c0 != nullptr)
364f554add5SHoward Hinnant {
365f554add5SHoward Hinnant i->__c_ = c0;
366f554add5SHoward Hinnant i->__c_->__add(i);
367f554add5SHoward Hinnant }
368f554add5SHoward Hinnant }
369f554add5SHoward Hinnant }
370f554add5SHoward Hinnant }
371f554add5SHoward Hinnant
372f554add5SHoward Hinnant bool
__dereferenceable(const void * __i) const373f554add5SHoward Hinnant __libcpp_db::__dereferenceable(const void* __i) const
374f554add5SHoward Hinnant {
375b3fcc67fSJonathan Roelofs #ifndef _LIBCPP_HAS_NO_THREADS
376f554add5SHoward Hinnant RLock _(mut());
377b3fcc67fSJonathan Roelofs #endif
378f554add5SHoward Hinnant __i_node* i = __find_iterator(__i);
379f554add5SHoward Hinnant return i != nullptr && i->__c_ != nullptr && i->__c_->__dereferenceable(__i);
380f554add5SHoward Hinnant }
381f554add5SHoward Hinnant
382f554add5SHoward Hinnant bool
__decrementable(const void * __i) const383f554add5SHoward Hinnant __libcpp_db::__decrementable(const void* __i) const
384f554add5SHoward Hinnant {
385b3fcc67fSJonathan Roelofs #ifndef _LIBCPP_HAS_NO_THREADS
386f554add5SHoward Hinnant RLock _(mut());
387b3fcc67fSJonathan Roelofs #endif
388f554add5SHoward Hinnant __i_node* i = __find_iterator(__i);
389f554add5SHoward Hinnant return i != nullptr && i->__c_ != nullptr && i->__c_->__decrementable(__i);
390f554add5SHoward Hinnant }
391f554add5SHoward Hinnant
392f554add5SHoward Hinnant bool
__addable(const void * __i,ptrdiff_t __n) const393f554add5SHoward Hinnant __libcpp_db::__addable(const void* __i, ptrdiff_t __n) const
394f554add5SHoward Hinnant {
395b3fcc67fSJonathan Roelofs #ifndef _LIBCPP_HAS_NO_THREADS
396f554add5SHoward Hinnant RLock _(mut());
397b3fcc67fSJonathan Roelofs #endif
398f554add5SHoward Hinnant __i_node* i = __find_iterator(__i);
399f554add5SHoward Hinnant return i != nullptr && i->__c_ != nullptr && i->__c_->__addable(__i, __n);
400f554add5SHoward Hinnant }
401f554add5SHoward Hinnant
402f554add5SHoward Hinnant bool
__subscriptable(const void * __i,ptrdiff_t __n) const403f554add5SHoward Hinnant __libcpp_db::__subscriptable(const void* __i, ptrdiff_t __n) const
404f554add5SHoward Hinnant {
405b3fcc67fSJonathan Roelofs #ifndef _LIBCPP_HAS_NO_THREADS
406f554add5SHoward Hinnant RLock _(mut());
407b3fcc67fSJonathan Roelofs #endif
408f554add5SHoward Hinnant __i_node* i = __find_iterator(__i);
409f554add5SHoward Hinnant return i != nullptr && i->__c_ != nullptr && i->__c_->__subscriptable(__i, __n);
410f554add5SHoward Hinnant }
411f554add5SHoward Hinnant
412f554add5SHoward Hinnant bool
__less_than_comparable(const void * __i,const void * __j) const41342a3046eSHoward Hinnant __libcpp_db::__less_than_comparable(const void* __i, const void* __j) const
414f554add5SHoward Hinnant {
415b3fcc67fSJonathan Roelofs #ifndef _LIBCPP_HAS_NO_THREADS
416f554add5SHoward Hinnant RLock _(mut());
417b3fcc67fSJonathan Roelofs #endif
418f554add5SHoward Hinnant __i_node* i = __find_iterator(__i);
419f554add5SHoward Hinnant __i_node* j = __find_iterator(__j);
420f554add5SHoward Hinnant __c_node* ci = i != nullptr ? i->__c_ : nullptr;
421f554add5SHoward Hinnant __c_node* cj = j != nullptr ? j->__c_ : nullptr;
422bbc6893bSArthur O'Dwyer return ci == cj;
423f554add5SHoward Hinnant }
424f554add5SHoward Hinnant
425f554add5SHoward Hinnant void
swap(void * c1,void * c2)426f554add5SHoward Hinnant __libcpp_db::swap(void* c1, void* c2)
427f554add5SHoward Hinnant {
428b3fcc67fSJonathan Roelofs #ifndef _LIBCPP_HAS_NO_THREADS
429f554add5SHoward Hinnant WLock _(mut());
430b3fcc67fSJonathan Roelofs #endif
431c206366fSHoward Hinnant size_t hc = hash<void*>()(c1) % static_cast<size_t>(__cend_ - __cbeg_);
432f554add5SHoward Hinnant __c_node* p1 = __cbeg_[hc];
433f554add5SHoward Hinnant _LIBCPP_ASSERT(p1 != nullptr, "debug mode internal logic error swap A");
434f554add5SHoward Hinnant while (p1->__c_ != c1)
435f554add5SHoward Hinnant {
436f554add5SHoward Hinnant p1 = p1->__next_;
437f554add5SHoward Hinnant _LIBCPP_ASSERT(p1 != nullptr, "debug mode internal logic error swap B");
438f554add5SHoward Hinnant }
439c206366fSHoward Hinnant hc = hash<void*>()(c2) % static_cast<size_t>(__cend_ - __cbeg_);
440f554add5SHoward Hinnant __c_node* p2 = __cbeg_[hc];
441f554add5SHoward Hinnant _LIBCPP_ASSERT(p2 != nullptr, "debug mode internal logic error swap C");
442f554add5SHoward Hinnant while (p2->__c_ != c2)
443f554add5SHoward Hinnant {
444f554add5SHoward Hinnant p2 = p2->__next_;
445f554add5SHoward Hinnant _LIBCPP_ASSERT(p2 != nullptr, "debug mode internal logic error swap D");
446f554add5SHoward Hinnant }
447f554add5SHoward Hinnant std::swap(p1->beg_, p2->beg_);
448f554add5SHoward Hinnant std::swap(p1->end_, p2->end_);
449f554add5SHoward Hinnant std::swap(p1->cap_, p2->cap_);
450f554add5SHoward Hinnant for (__i_node** p = p1->beg_; p != p1->end_; ++p)
451f554add5SHoward Hinnant (*p)->__c_ = p1;
452f554add5SHoward Hinnant for (__i_node** p = p2->beg_; p != p2->end_; ++p)
453f554add5SHoward Hinnant (*p)->__c_ = p2;
454f554add5SHoward Hinnant }
455f554add5SHoward Hinnant
456c36bfc49SHoward Hinnant void
__insert_i(void * __i)457c36bfc49SHoward Hinnant __libcpp_db::__insert_i(void* __i)
458c36bfc49SHoward Hinnant {
459b3fcc67fSJonathan Roelofs #ifndef _LIBCPP_HAS_NO_THREADS
460c36bfc49SHoward Hinnant WLock _(mut());
461b3fcc67fSJonathan Roelofs #endif
462c36bfc49SHoward Hinnant __insert_iterator(__i);
463c36bfc49SHoward Hinnant }
464c36bfc49SHoward Hinnant
465920b56caSHoward Hinnant void
__add(__i_node * i)466920b56caSHoward Hinnant __c_node::__add(__i_node* i)
467920b56caSHoward Hinnant {
468920b56caSHoward Hinnant if (end_ == cap_)
469920b56caSHoward Hinnant {
470c206366fSHoward Hinnant size_t nc = 2*static_cast<size_t>(cap_ - beg_);
471920b56caSHoward Hinnant if (nc == 0)
472920b56caSHoward Hinnant nc = 1;
47385ad6c99SJoerg Sonnenberger __i_node** beg =
47485ad6c99SJoerg Sonnenberger static_cast<__i_node**>(malloc(nc * sizeof(__i_node*)));
475920b56caSHoward Hinnant if (beg == nullptr)
476d437fa5cSMarshall Clow __throw_bad_alloc();
477d437fa5cSMarshall Clow
478920b56caSHoward Hinnant if (nc > 1)
479920b56caSHoward Hinnant memcpy(beg, beg_, nc/2*sizeof(__i_node*));
480920b56caSHoward Hinnant free(beg_);
481920b56caSHoward Hinnant beg_ = beg;
482920b56caSHoward Hinnant end_ = beg_ + nc/2;
483920b56caSHoward Hinnant cap_ = beg_ + nc;
484920b56caSHoward Hinnant }
485920b56caSHoward Hinnant *end_++ = i;
486920b56caSHoward Hinnant }
487920b56caSHoward Hinnant
488f554add5SHoward Hinnant // private api
489f554add5SHoward Hinnant
490f554add5SHoward Hinnant _LIBCPP_HIDDEN
491f554add5SHoward Hinnant __i_node*
__insert_iterator(void * __i)492f554add5SHoward Hinnant __libcpp_db::__insert_iterator(void* __i)
493f554add5SHoward Hinnant {
494c206366fSHoward Hinnant if (__isz_ + 1 > static_cast<size_t>(__iend_ - __ibeg_))
495f554add5SHoward Hinnant {
496c206366fSHoward Hinnant size_t nc = __next_prime(2*static_cast<size_t>(__iend_ - __ibeg_) + 1);
497cb843f5bSLouis Dionne __i_node** ibeg = static_cast<__i_node**>(calloc(nc, sizeof(__i_node*)));
498f554add5SHoward Hinnant if (ibeg == nullptr)
499d437fa5cSMarshall Clow __throw_bad_alloc();
500d437fa5cSMarshall Clow
501f554add5SHoward Hinnant for (__i_node** p = __ibeg_; p != __iend_; ++p)
502f554add5SHoward Hinnant {
503f554add5SHoward Hinnant __i_node* q = *p;
504f554add5SHoward Hinnant while (q != nullptr)
505f554add5SHoward Hinnant {
506f554add5SHoward Hinnant size_t h = hash<void*>()(q->__i_) % nc;
507f554add5SHoward Hinnant __i_node* r = q->__next_;
508f554add5SHoward Hinnant q->__next_ = ibeg[h];
509f554add5SHoward Hinnant ibeg[h] = q;
510f554add5SHoward Hinnant q = r;
511f554add5SHoward Hinnant }
512f554add5SHoward Hinnant }
513f554add5SHoward Hinnant free(__ibeg_);
514f554add5SHoward Hinnant __ibeg_ = ibeg;
515f554add5SHoward Hinnant __iend_ = __ibeg_ + nc;
516f554add5SHoward Hinnant }
517c206366fSHoward Hinnant size_t hi = hash<void*>()(__i) % static_cast<size_t>(__iend_ - __ibeg_);
518f554add5SHoward Hinnant __i_node* p = __ibeg_[hi];
51985ad6c99SJoerg Sonnenberger __i_node* r = __ibeg_[hi] =
52085ad6c99SJoerg Sonnenberger static_cast<__i_node*>(malloc(sizeof(__i_node)));
521f554add5SHoward Hinnant if (r == nullptr)
522d437fa5cSMarshall Clow __throw_bad_alloc();
523d437fa5cSMarshall Clow
524f554add5SHoward Hinnant ::new(r) __i_node(__i, p, nullptr);
525f554add5SHoward Hinnant ++__isz_;
526f554add5SHoward Hinnant return r;
527f554add5SHoward Hinnant }
528f554add5SHoward Hinnant
529f554add5SHoward Hinnant _LIBCPP_HIDDEN
530f554add5SHoward Hinnant __i_node*
__find_iterator(const void * __i) const531f554add5SHoward Hinnant __libcpp_db::__find_iterator(const void* __i) const
532f554add5SHoward Hinnant {
533f554add5SHoward Hinnant __i_node* r = nullptr;
534f554add5SHoward Hinnant if (__ibeg_ != __iend_)
535f554add5SHoward Hinnant {
536c206366fSHoward Hinnant size_t h = hash<const void*>()(__i) % static_cast<size_t>(__iend_ - __ibeg_);
537f554add5SHoward Hinnant for (__i_node* nd = __ibeg_[h]; nd != nullptr; nd = nd->__next_)
538f554add5SHoward Hinnant {
539f554add5SHoward Hinnant if (nd->__i_ == __i)
540f554add5SHoward Hinnant {
541f554add5SHoward Hinnant r = nd;
542f554add5SHoward Hinnant break;
543f554add5SHoward Hinnant }
544f554add5SHoward Hinnant }
545f554add5SHoward Hinnant }
546f554add5SHoward Hinnant return r;
547f554add5SHoward Hinnant }
548f554add5SHoward Hinnant
549f554add5SHoward Hinnant _LIBCPP_HIDDEN
550f554add5SHoward Hinnant void
__remove(__i_node * p)551f554add5SHoward Hinnant __c_node::__remove(__i_node* p)
552f554add5SHoward Hinnant {
553f554add5SHoward Hinnant __i_node** r = find(beg_, end_, p);
554f554add5SHoward Hinnant _LIBCPP_ASSERT(r != end_, "debug mode internal logic error __c_node::__remove");
555f554add5SHoward Hinnant if (--end_ != r)
556c206366fSHoward Hinnant memmove(r, r+1, static_cast<size_t>(end_ - r)*sizeof(__i_node*));
557f554add5SHoward Hinnant }
558f554add5SHoward Hinnant
559f554add5SHoward Hinnant _LIBCPP_END_NAMESPACE_STD
560