xref: /llvm-project-15.0.7/libcxx/src/debug.cpp (revision f87aa19b)
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