xref: /minix3/external/bsd/libc++/dist/libcxx/src/debug.cpp (revision 4684ddb6aab0b36791c8099bc705d6140b3d05d0)
1*4684ddb6SLionel Sambuc //===-------------------------- debug.cpp ---------------------------------===//
2*4684ddb6SLionel Sambuc //
3*4684ddb6SLionel Sambuc //                     The LLVM Compiler Infrastructure
4*4684ddb6SLionel Sambuc //
5*4684ddb6SLionel Sambuc // This file is dual licensed under the MIT and the University of Illinois Open
6*4684ddb6SLionel Sambuc // Source Licenses. See LICENSE.TXT for details.
7*4684ddb6SLionel Sambuc //
8*4684ddb6SLionel Sambuc //===----------------------------------------------------------------------===//
9*4684ddb6SLionel Sambuc 
10*4684ddb6SLionel Sambuc #define _LIBCPP_DEBUG 1
11*4684ddb6SLionel Sambuc #include "__config"
12*4684ddb6SLionel Sambuc #include "__debug"
13*4684ddb6SLionel Sambuc #include "functional"
14*4684ddb6SLionel Sambuc #include "algorithm"
15*4684ddb6SLionel Sambuc #include "__hash_table"
16*4684ddb6SLionel Sambuc #include "mutex"
17*4684ddb6SLionel Sambuc 
18*4684ddb6SLionel Sambuc _LIBCPP_BEGIN_NAMESPACE_STD
19*4684ddb6SLionel Sambuc 
20*4684ddb6SLionel Sambuc _LIBCPP_FUNC_VIS
21*4684ddb6SLionel Sambuc __libcpp_db*
22*4684ddb6SLionel Sambuc __get_db()
23*4684ddb6SLionel Sambuc {
24*4684ddb6SLionel Sambuc     static __libcpp_db db;
25*4684ddb6SLionel Sambuc     return &db;
26*4684ddb6SLionel Sambuc }
27*4684ddb6SLionel Sambuc 
28*4684ddb6SLionel Sambuc _LIBCPP_FUNC_VIS
29*4684ddb6SLionel Sambuc const __libcpp_db*
30*4684ddb6SLionel Sambuc __get_const_db()
31*4684ddb6SLionel Sambuc {
32*4684ddb6SLionel Sambuc     return __get_db();
33*4684ddb6SLionel Sambuc }
34*4684ddb6SLionel Sambuc 
35*4684ddb6SLionel Sambuc namespace
36*4684ddb6SLionel Sambuc {
37*4684ddb6SLionel Sambuc 
38*4684ddb6SLionel Sambuc typedef mutex mutex_type;
39*4684ddb6SLionel Sambuc typedef lock_guard<mutex_type> WLock;
40*4684ddb6SLionel Sambuc typedef lock_guard<mutex_type> RLock;
41*4684ddb6SLionel Sambuc 
42*4684ddb6SLionel Sambuc mutex_type&
43*4684ddb6SLionel Sambuc mut()
44*4684ddb6SLionel Sambuc {
45*4684ddb6SLionel Sambuc     static mutex_type m;
46*4684ddb6SLionel Sambuc     return m;
47*4684ddb6SLionel Sambuc }
48*4684ddb6SLionel Sambuc 
49*4684ddb6SLionel Sambuc }  // unnamed namespace
50*4684ddb6SLionel Sambuc 
51*4684ddb6SLionel Sambuc __i_node::~__i_node()
52*4684ddb6SLionel Sambuc {
53*4684ddb6SLionel Sambuc     if (__next_)
54*4684ddb6SLionel Sambuc     {
55*4684ddb6SLionel Sambuc         __next_->~__i_node();
56*4684ddb6SLionel Sambuc         free(__next_);
57*4684ddb6SLionel Sambuc     }
58*4684ddb6SLionel Sambuc }
59*4684ddb6SLionel Sambuc 
60*4684ddb6SLionel Sambuc __c_node::~__c_node()
61*4684ddb6SLionel Sambuc {
62*4684ddb6SLionel Sambuc     free(beg_);
63*4684ddb6SLionel Sambuc     if (__next_)
64*4684ddb6SLionel Sambuc     {
65*4684ddb6SLionel Sambuc         __next_->~__c_node();
66*4684ddb6SLionel Sambuc         free(__next_);
67*4684ddb6SLionel Sambuc     }
68*4684ddb6SLionel Sambuc }
69*4684ddb6SLionel Sambuc 
70*4684ddb6SLionel Sambuc __libcpp_db::__libcpp_db()
71*4684ddb6SLionel Sambuc     : __cbeg_(nullptr),
72*4684ddb6SLionel Sambuc       __cend_(nullptr),
73*4684ddb6SLionel Sambuc       __csz_(0),
74*4684ddb6SLionel Sambuc       __ibeg_(nullptr),
75*4684ddb6SLionel Sambuc       __iend_(nullptr),
76*4684ddb6SLionel Sambuc       __isz_(0)
77*4684ddb6SLionel Sambuc {
78*4684ddb6SLionel Sambuc }
79*4684ddb6SLionel Sambuc 
80*4684ddb6SLionel Sambuc __libcpp_db::~__libcpp_db()
81*4684ddb6SLionel Sambuc {
82*4684ddb6SLionel Sambuc     if (__cbeg_)
83*4684ddb6SLionel Sambuc     {
84*4684ddb6SLionel Sambuc         for (__c_node** p = __cbeg_; p != __cend_; ++p)
85*4684ddb6SLionel Sambuc         {
86*4684ddb6SLionel Sambuc             if (*p != nullptr)
87*4684ddb6SLionel Sambuc             {
88*4684ddb6SLionel Sambuc                 (*p)->~__c_node();
89*4684ddb6SLionel Sambuc                 free(*p);
90*4684ddb6SLionel Sambuc             }
91*4684ddb6SLionel Sambuc         }
92*4684ddb6SLionel Sambuc         free(__cbeg_);
93*4684ddb6SLionel Sambuc     }
94*4684ddb6SLionel Sambuc     if (__ibeg_)
95*4684ddb6SLionel Sambuc     {
96*4684ddb6SLionel Sambuc         for (__i_node** p = __ibeg_; p != __iend_; ++p)
97*4684ddb6SLionel Sambuc         {
98*4684ddb6SLionel Sambuc             if (*p != nullptr)
99*4684ddb6SLionel Sambuc             {
100*4684ddb6SLionel Sambuc                 (*p)->~__i_node();
101*4684ddb6SLionel Sambuc                 free(*p);
102*4684ddb6SLionel Sambuc             }
103*4684ddb6SLionel Sambuc         }
104*4684ddb6SLionel Sambuc         free(__ibeg_);
105*4684ddb6SLionel Sambuc     }
106*4684ddb6SLionel Sambuc }
107*4684ddb6SLionel Sambuc 
108*4684ddb6SLionel Sambuc void*
109*4684ddb6SLionel Sambuc __libcpp_db::__find_c_from_i(void* __i) const
110*4684ddb6SLionel Sambuc {
111*4684ddb6SLionel Sambuc     RLock _(mut());
112*4684ddb6SLionel Sambuc     __i_node* i = __find_iterator(__i);
113*4684ddb6SLionel Sambuc     _LIBCPP_ASSERT(i != nullptr, "iterator not found in debug database.");
114*4684ddb6SLionel Sambuc     return i->__c_ != nullptr ? i->__c_->__c_ : nullptr;
115*4684ddb6SLionel Sambuc }
116*4684ddb6SLionel Sambuc 
117*4684ddb6SLionel Sambuc void
118*4684ddb6SLionel Sambuc __libcpp_db::__insert_ic(void* __i, const void* __c)
119*4684ddb6SLionel Sambuc {
120*4684ddb6SLionel Sambuc     WLock _(mut());
121*4684ddb6SLionel Sambuc     if (__cbeg_ == __cend_)
122*4684ddb6SLionel Sambuc         return;
123*4684ddb6SLionel Sambuc     size_t hc = hash<const void*>()(__c) % static_cast<size_t>(__cend_ - __cbeg_);
124*4684ddb6SLionel Sambuc     __c_node* c = __cbeg_[hc];
125*4684ddb6SLionel Sambuc     if (c == nullptr)
126*4684ddb6SLionel Sambuc         return;
127*4684ddb6SLionel Sambuc     while (c->__c_ != __c)
128*4684ddb6SLionel Sambuc     {
129*4684ddb6SLionel Sambuc         c = c->__next_;
130*4684ddb6SLionel Sambuc         if (c == nullptr)
131*4684ddb6SLionel Sambuc             return;
132*4684ddb6SLionel Sambuc     }
133*4684ddb6SLionel Sambuc     __i_node* i = __insert_iterator(__i);
134*4684ddb6SLionel Sambuc     c->__add(i);
135*4684ddb6SLionel Sambuc     i->__c_ = c;
136*4684ddb6SLionel Sambuc }
137*4684ddb6SLionel Sambuc 
138*4684ddb6SLionel Sambuc __c_node*
139*4684ddb6SLionel Sambuc __libcpp_db::__insert_c(void* __c)
140*4684ddb6SLionel Sambuc {
141*4684ddb6SLionel Sambuc     WLock _(mut());
142*4684ddb6SLionel Sambuc     if (__csz_ + 1 > static_cast<size_t>(__cend_ - __cbeg_))
143*4684ddb6SLionel Sambuc     {
144*4684ddb6SLionel Sambuc         size_t nc = __next_prime(2*static_cast<size_t>(__cend_ - __cbeg_) + 1);
145*4684ddb6SLionel Sambuc         __c_node** cbeg = static_cast<__c_node**>(calloc(nc, sizeof(void*)));
146*4684ddb6SLionel Sambuc         if (cbeg == nullptr)
147*4684ddb6SLionel Sambuc #ifndef _LIBCPP_NO_EXCEPTIONS
148*4684ddb6SLionel Sambuc             throw bad_alloc();
149*4684ddb6SLionel Sambuc #else
150*4684ddb6SLionel Sambuc             abort();
151*4684ddb6SLionel Sambuc #endif
152*4684ddb6SLionel Sambuc         for (__c_node** p = __cbeg_; p != __cend_; ++p)
153*4684ddb6SLionel Sambuc         {
154*4684ddb6SLionel Sambuc             __c_node* q = *p;
155*4684ddb6SLionel Sambuc             while (q != nullptr)
156*4684ddb6SLionel Sambuc             {
157*4684ddb6SLionel Sambuc                 size_t h = hash<void*>()(q->__c_) % nc;
158*4684ddb6SLionel Sambuc                 __c_node* r = q->__next_;
159*4684ddb6SLionel Sambuc                 q->__next_ = cbeg[h];
160*4684ddb6SLionel Sambuc                 cbeg[h] = q;
161*4684ddb6SLionel Sambuc                 q = r;
162*4684ddb6SLionel Sambuc             }
163*4684ddb6SLionel Sambuc         }
164*4684ddb6SLionel Sambuc         free(__cbeg_);
165*4684ddb6SLionel Sambuc         __cbeg_ = cbeg;
166*4684ddb6SLionel Sambuc         __cend_ = __cbeg_ + nc;
167*4684ddb6SLionel Sambuc     }
168*4684ddb6SLionel Sambuc     size_t hc = hash<void*>()(__c) % static_cast<size_t>(__cend_ - __cbeg_);
169*4684ddb6SLionel Sambuc     __c_node* p = __cbeg_[hc];
170*4684ddb6SLionel Sambuc     __c_node* r = __cbeg_[hc] =
171*4684ddb6SLionel Sambuc       static_cast<__c_node*>(malloc(sizeof(__c_node)));
172*4684ddb6SLionel Sambuc     if (__cbeg_[hc] == nullptr)
173*4684ddb6SLionel Sambuc #ifndef _LIBCPP_NO_EXCEPTIONS
174*4684ddb6SLionel Sambuc         throw bad_alloc();
175*4684ddb6SLionel Sambuc #else
176*4684ddb6SLionel Sambuc         abort();
177*4684ddb6SLionel Sambuc #endif
178*4684ddb6SLionel Sambuc     r->__c_ = __c;
179*4684ddb6SLionel Sambuc     r->__next_ = p;
180*4684ddb6SLionel Sambuc     ++__csz_;
181*4684ddb6SLionel Sambuc     return r;
182*4684ddb6SLionel Sambuc }
183*4684ddb6SLionel Sambuc 
184*4684ddb6SLionel Sambuc void
185*4684ddb6SLionel Sambuc __libcpp_db::__erase_i(void* __i)
186*4684ddb6SLionel Sambuc {
187*4684ddb6SLionel Sambuc     WLock _(mut());
188*4684ddb6SLionel Sambuc     if (__ibeg_ != __iend_)
189*4684ddb6SLionel Sambuc     {
190*4684ddb6SLionel Sambuc         size_t hi = hash<void*>()(__i) % static_cast<size_t>(__iend_ - __ibeg_);
191*4684ddb6SLionel Sambuc         __i_node* p = __ibeg_[hi];
192*4684ddb6SLionel Sambuc         if (p != nullptr)
193*4684ddb6SLionel Sambuc         {
194*4684ddb6SLionel Sambuc             __i_node* q = nullptr;
195*4684ddb6SLionel Sambuc             while (p->__i_ != __i)
196*4684ddb6SLionel Sambuc             {
197*4684ddb6SLionel Sambuc                 q = p;
198*4684ddb6SLionel Sambuc                 p = p->__next_;
199*4684ddb6SLionel Sambuc                 if (p == nullptr)
200*4684ddb6SLionel Sambuc                     return;
201*4684ddb6SLionel Sambuc             }
202*4684ddb6SLionel Sambuc             if (q == nullptr)
203*4684ddb6SLionel Sambuc                 __ibeg_[hi] = p->__next_;
204*4684ddb6SLionel Sambuc             else
205*4684ddb6SLionel Sambuc                 q->__next_ = p->__next_;
206*4684ddb6SLionel Sambuc             __c_node* c = p->__c_;
207*4684ddb6SLionel Sambuc             free(p);
208*4684ddb6SLionel Sambuc             --__isz_;
209*4684ddb6SLionel Sambuc             if (c != nullptr)
210*4684ddb6SLionel Sambuc                 c->__remove(p);
211*4684ddb6SLionel Sambuc         }
212*4684ddb6SLionel Sambuc     }
213*4684ddb6SLionel Sambuc }
214*4684ddb6SLionel Sambuc 
215*4684ddb6SLionel Sambuc void
216*4684ddb6SLionel Sambuc __libcpp_db::__invalidate_all(void* __c)
217*4684ddb6SLionel Sambuc {
218*4684ddb6SLionel Sambuc     WLock _(mut());
219*4684ddb6SLionel Sambuc     if (__cend_ != __cbeg_)
220*4684ddb6SLionel Sambuc     {
221*4684ddb6SLionel Sambuc         size_t hc = hash<void*>()(__c) % static_cast<size_t>(__cend_ - __cbeg_);
222*4684ddb6SLionel Sambuc         __c_node* p = __cbeg_[hc];
223*4684ddb6SLionel Sambuc         if (p == nullptr)
224*4684ddb6SLionel Sambuc             return;
225*4684ddb6SLionel Sambuc         while (p->__c_ != __c)
226*4684ddb6SLionel Sambuc         {
227*4684ddb6SLionel Sambuc             p = p->__next_;
228*4684ddb6SLionel Sambuc             if (p == nullptr)
229*4684ddb6SLionel Sambuc                 return;
230*4684ddb6SLionel Sambuc         }
231*4684ddb6SLionel Sambuc         while (p->end_ != p->beg_)
232*4684ddb6SLionel Sambuc         {
233*4684ddb6SLionel Sambuc             --p->end_;
234*4684ddb6SLionel Sambuc             (*p->end_)->__c_ = nullptr;
235*4684ddb6SLionel Sambuc         }
236*4684ddb6SLionel Sambuc     }
237*4684ddb6SLionel Sambuc }
238*4684ddb6SLionel Sambuc 
239*4684ddb6SLionel Sambuc __c_node*
240*4684ddb6SLionel Sambuc __libcpp_db::__find_c_and_lock(void* __c) const
241*4684ddb6SLionel Sambuc {
242*4684ddb6SLionel Sambuc     mut().lock();
243*4684ddb6SLionel Sambuc     if (__cend_ == __cbeg_)
244*4684ddb6SLionel Sambuc     {
245*4684ddb6SLionel Sambuc         mut().unlock();
246*4684ddb6SLionel Sambuc         return nullptr;
247*4684ddb6SLionel Sambuc     }
248*4684ddb6SLionel Sambuc     size_t hc = hash<void*>()(__c) % static_cast<size_t>(__cend_ - __cbeg_);
249*4684ddb6SLionel Sambuc     __c_node* p = __cbeg_[hc];
250*4684ddb6SLionel Sambuc     if (p == nullptr)
251*4684ddb6SLionel Sambuc     {
252*4684ddb6SLionel Sambuc         mut().unlock();
253*4684ddb6SLionel Sambuc         return nullptr;
254*4684ddb6SLionel Sambuc     }
255*4684ddb6SLionel Sambuc     while (p->__c_ != __c)
256*4684ddb6SLionel Sambuc     {
257*4684ddb6SLionel Sambuc         p = p->__next_;
258*4684ddb6SLionel Sambuc         if (p == nullptr)
259*4684ddb6SLionel Sambuc         {
260*4684ddb6SLionel Sambuc             mut().unlock();
261*4684ddb6SLionel Sambuc             return nullptr;
262*4684ddb6SLionel Sambuc         }
263*4684ddb6SLionel Sambuc     }
264*4684ddb6SLionel Sambuc     return p;
265*4684ddb6SLionel Sambuc }
266*4684ddb6SLionel Sambuc 
267*4684ddb6SLionel Sambuc __c_node*
268*4684ddb6SLionel Sambuc __libcpp_db::__find_c(void* __c) const
269*4684ddb6SLionel Sambuc {
270*4684ddb6SLionel Sambuc     size_t hc = hash<void*>()(__c) % static_cast<size_t>(__cend_ - __cbeg_);
271*4684ddb6SLionel Sambuc     __c_node* p = __cbeg_[hc];
272*4684ddb6SLionel Sambuc     _LIBCPP_ASSERT(p != nullptr, "debug mode internal logic error __find_c A");
273*4684ddb6SLionel Sambuc     while (p->__c_ != __c)
274*4684ddb6SLionel Sambuc     {
275*4684ddb6SLionel Sambuc         p = p->__next_;
276*4684ddb6SLionel Sambuc         _LIBCPP_ASSERT(p != nullptr, "debug mode internal logic error __find_c B");
277*4684ddb6SLionel Sambuc     }
278*4684ddb6SLionel Sambuc     return p;
279*4684ddb6SLionel Sambuc }
280*4684ddb6SLionel Sambuc 
281*4684ddb6SLionel Sambuc void
282*4684ddb6SLionel Sambuc __libcpp_db::unlock() const
283*4684ddb6SLionel Sambuc {
284*4684ddb6SLionel Sambuc     mut().unlock();
285*4684ddb6SLionel Sambuc }
286*4684ddb6SLionel Sambuc 
287*4684ddb6SLionel Sambuc void
288*4684ddb6SLionel Sambuc __libcpp_db::__erase_c(void* __c)
289*4684ddb6SLionel Sambuc {
290*4684ddb6SLionel Sambuc     WLock _(mut());
291*4684ddb6SLionel Sambuc     if (__cend_ != __cbeg_)
292*4684ddb6SLionel Sambuc     {
293*4684ddb6SLionel Sambuc         size_t hc = hash<void*>()(__c) % static_cast<size_t>(__cend_ - __cbeg_);
294*4684ddb6SLionel Sambuc         __c_node* p = __cbeg_[hc];
295*4684ddb6SLionel Sambuc         if (p == nullptr)
296*4684ddb6SLionel Sambuc             return;
297*4684ddb6SLionel Sambuc         __c_node* q = nullptr;
298*4684ddb6SLionel Sambuc         _LIBCPP_ASSERT(p != nullptr, "debug mode internal logic error __erase_c A");
299*4684ddb6SLionel Sambuc         while (p->__c_ != __c)
300*4684ddb6SLionel Sambuc         {
301*4684ddb6SLionel Sambuc             q = p;
302*4684ddb6SLionel Sambuc             p = p->__next_;
303*4684ddb6SLionel Sambuc             if (p == nullptr)
304*4684ddb6SLionel Sambuc                 return;
305*4684ddb6SLionel Sambuc             _LIBCPP_ASSERT(p != nullptr, "debug mode internal logic error __erase_c B");
306*4684ddb6SLionel Sambuc         }
307*4684ddb6SLionel Sambuc         if (q == nullptr)
308*4684ddb6SLionel Sambuc             __cbeg_[hc] = p->__next_;
309*4684ddb6SLionel Sambuc         else
310*4684ddb6SLionel Sambuc             q->__next_ = p->__next_;
311*4684ddb6SLionel Sambuc         while (p->end_ != p->beg_)
312*4684ddb6SLionel Sambuc         {
313*4684ddb6SLionel Sambuc             --p->end_;
314*4684ddb6SLionel Sambuc             (*p->end_)->__c_ = nullptr;
315*4684ddb6SLionel Sambuc         }
316*4684ddb6SLionel Sambuc         free(p->beg_);
317*4684ddb6SLionel Sambuc         free(p);
318*4684ddb6SLionel Sambuc         --__csz_;
319*4684ddb6SLionel Sambuc     }
320*4684ddb6SLionel Sambuc }
321*4684ddb6SLionel Sambuc 
322*4684ddb6SLionel Sambuc void
323*4684ddb6SLionel Sambuc __libcpp_db::__iterator_copy(void* __i, const void* __i0)
324*4684ddb6SLionel Sambuc {
325*4684ddb6SLionel Sambuc     WLock _(mut());
326*4684ddb6SLionel Sambuc     __i_node* i = __find_iterator(__i);
327*4684ddb6SLionel Sambuc     __i_node* i0 = __find_iterator(__i0);
328*4684ddb6SLionel Sambuc     __c_node* c0 = i0 != nullptr ? i0->__c_ : nullptr;
329*4684ddb6SLionel Sambuc     if (i == nullptr && i0 != nullptr)
330*4684ddb6SLionel Sambuc         i = __insert_iterator(__i);
331*4684ddb6SLionel Sambuc     __c_node* c = i != nullptr ? i->__c_ : nullptr;
332*4684ddb6SLionel Sambuc     if (c != c0)
333*4684ddb6SLionel Sambuc     {
334*4684ddb6SLionel Sambuc         if (c != nullptr)
335*4684ddb6SLionel Sambuc             c->__remove(i);
336*4684ddb6SLionel Sambuc         if (i != nullptr)
337*4684ddb6SLionel Sambuc         {
338*4684ddb6SLionel Sambuc             i->__c_ = nullptr;
339*4684ddb6SLionel Sambuc             if (c0 != nullptr)
340*4684ddb6SLionel Sambuc             {
341*4684ddb6SLionel Sambuc                 i->__c_ = c0;
342*4684ddb6SLionel Sambuc                 i->__c_->__add(i);
343*4684ddb6SLionel Sambuc             }
344*4684ddb6SLionel Sambuc         }
345*4684ddb6SLionel Sambuc     }
346*4684ddb6SLionel Sambuc }
347*4684ddb6SLionel Sambuc 
348*4684ddb6SLionel Sambuc bool
349*4684ddb6SLionel Sambuc __libcpp_db::__dereferenceable(const void* __i) const
350*4684ddb6SLionel Sambuc {
351*4684ddb6SLionel Sambuc     RLock _(mut());
352*4684ddb6SLionel Sambuc     __i_node* i = __find_iterator(__i);
353*4684ddb6SLionel Sambuc     return i != nullptr && i->__c_ != nullptr && i->__c_->__dereferenceable(__i);
354*4684ddb6SLionel Sambuc }
355*4684ddb6SLionel Sambuc 
356*4684ddb6SLionel Sambuc bool
357*4684ddb6SLionel Sambuc __libcpp_db::__decrementable(const void* __i) const
358*4684ddb6SLionel Sambuc {
359*4684ddb6SLionel Sambuc     RLock _(mut());
360*4684ddb6SLionel Sambuc     __i_node* i = __find_iterator(__i);
361*4684ddb6SLionel Sambuc     return i != nullptr && i->__c_ != nullptr && i->__c_->__decrementable(__i);
362*4684ddb6SLionel Sambuc }
363*4684ddb6SLionel Sambuc 
364*4684ddb6SLionel Sambuc bool
365*4684ddb6SLionel Sambuc __libcpp_db::__addable(const void* __i, ptrdiff_t __n) const
366*4684ddb6SLionel Sambuc {
367*4684ddb6SLionel Sambuc     RLock _(mut());
368*4684ddb6SLionel Sambuc     __i_node* i = __find_iterator(__i);
369*4684ddb6SLionel Sambuc     return i != nullptr && i->__c_ != nullptr && i->__c_->__addable(__i, __n);
370*4684ddb6SLionel Sambuc }
371*4684ddb6SLionel Sambuc 
372*4684ddb6SLionel Sambuc bool
373*4684ddb6SLionel Sambuc __libcpp_db::__subscriptable(const void* __i, ptrdiff_t __n) const
374*4684ddb6SLionel Sambuc {
375*4684ddb6SLionel Sambuc     RLock _(mut());
376*4684ddb6SLionel Sambuc     __i_node* i = __find_iterator(__i);
377*4684ddb6SLionel Sambuc     return i != nullptr && i->__c_ != nullptr && i->__c_->__subscriptable(__i, __n);
378*4684ddb6SLionel Sambuc }
379*4684ddb6SLionel Sambuc 
380*4684ddb6SLionel Sambuc bool
381*4684ddb6SLionel Sambuc __libcpp_db::__less_than_comparable(const void* __i, const void* __j) const
382*4684ddb6SLionel Sambuc {
383*4684ddb6SLionel Sambuc     RLock _(mut());
384*4684ddb6SLionel Sambuc     __i_node* i = __find_iterator(__i);
385*4684ddb6SLionel Sambuc     __i_node* j = __find_iterator(__j);
386*4684ddb6SLionel Sambuc     __c_node* ci = i != nullptr ? i->__c_ : nullptr;
387*4684ddb6SLionel Sambuc     __c_node* cj = j != nullptr ? j->__c_ : nullptr;
388*4684ddb6SLionel Sambuc     return ci != nullptr && ci == cj;
389*4684ddb6SLionel Sambuc }
390*4684ddb6SLionel Sambuc 
391*4684ddb6SLionel Sambuc void
392*4684ddb6SLionel Sambuc __libcpp_db::swap(void* c1, void* c2)
393*4684ddb6SLionel Sambuc {
394*4684ddb6SLionel Sambuc     WLock _(mut());
395*4684ddb6SLionel Sambuc     size_t hc = hash<void*>()(c1) % static_cast<size_t>(__cend_ - __cbeg_);
396*4684ddb6SLionel Sambuc     __c_node* p1 = __cbeg_[hc];
397*4684ddb6SLionel Sambuc     _LIBCPP_ASSERT(p1 != nullptr, "debug mode internal logic error swap A");
398*4684ddb6SLionel Sambuc     while (p1->__c_ != c1)
399*4684ddb6SLionel Sambuc     {
400*4684ddb6SLionel Sambuc         p1 = p1->__next_;
401*4684ddb6SLionel Sambuc         _LIBCPP_ASSERT(p1 != nullptr, "debug mode internal logic error swap B");
402*4684ddb6SLionel Sambuc     }
403*4684ddb6SLionel Sambuc     hc = hash<void*>()(c2) % static_cast<size_t>(__cend_ - __cbeg_);
404*4684ddb6SLionel Sambuc     __c_node* p2 = __cbeg_[hc];
405*4684ddb6SLionel Sambuc     _LIBCPP_ASSERT(p2 != nullptr, "debug mode internal logic error swap C");
406*4684ddb6SLionel Sambuc     while (p2->__c_ != c2)
407*4684ddb6SLionel Sambuc     {
408*4684ddb6SLionel Sambuc         p2 = p2->__next_;
409*4684ddb6SLionel Sambuc         _LIBCPP_ASSERT(p2 != nullptr, "debug mode internal logic error swap D");
410*4684ddb6SLionel Sambuc     }
411*4684ddb6SLionel Sambuc     std::swap(p1->beg_, p2->beg_);
412*4684ddb6SLionel Sambuc     std::swap(p1->end_, p2->end_);
413*4684ddb6SLionel Sambuc     std::swap(p1->cap_, p2->cap_);
414*4684ddb6SLionel Sambuc     for (__i_node** p = p1->beg_; p != p1->end_; ++p)
415*4684ddb6SLionel Sambuc         (*p)->__c_ = p1;
416*4684ddb6SLionel Sambuc     for (__i_node** p = p2->beg_; p != p2->end_; ++p)
417*4684ddb6SLionel Sambuc         (*p)->__c_ = p2;
418*4684ddb6SLionel Sambuc }
419*4684ddb6SLionel Sambuc 
420*4684ddb6SLionel Sambuc void
421*4684ddb6SLionel Sambuc __libcpp_db::__insert_i(void* __i)
422*4684ddb6SLionel Sambuc {
423*4684ddb6SLionel Sambuc     WLock _(mut());
424*4684ddb6SLionel Sambuc     __insert_iterator(__i);
425*4684ddb6SLionel Sambuc }
426*4684ddb6SLionel Sambuc 
427*4684ddb6SLionel Sambuc void
428*4684ddb6SLionel Sambuc __c_node::__add(__i_node* i)
429*4684ddb6SLionel Sambuc {
430*4684ddb6SLionel Sambuc     if (end_ == cap_)
431*4684ddb6SLionel Sambuc     {
432*4684ddb6SLionel Sambuc         size_t nc = 2*static_cast<size_t>(cap_ - beg_);
433*4684ddb6SLionel Sambuc         if (nc == 0)
434*4684ddb6SLionel Sambuc             nc = 1;
435*4684ddb6SLionel Sambuc         __i_node** beg =
436*4684ddb6SLionel Sambuc            static_cast<__i_node**>(malloc(nc * sizeof(__i_node*)));
437*4684ddb6SLionel Sambuc         if (beg == nullptr)
438*4684ddb6SLionel Sambuc #ifndef _LIBCPP_NO_EXCEPTIONS
439*4684ddb6SLionel Sambuc             throw bad_alloc();
440*4684ddb6SLionel Sambuc #else
441*4684ddb6SLionel Sambuc             abort();
442*4684ddb6SLionel Sambuc #endif
443*4684ddb6SLionel Sambuc         if (nc > 1)
444*4684ddb6SLionel Sambuc             memcpy(beg, beg_, nc/2*sizeof(__i_node*));
445*4684ddb6SLionel Sambuc         free(beg_);
446*4684ddb6SLionel Sambuc         beg_ = beg;
447*4684ddb6SLionel Sambuc         end_ = beg_ + nc/2;
448*4684ddb6SLionel Sambuc         cap_ = beg_ + nc;
449*4684ddb6SLionel Sambuc     }
450*4684ddb6SLionel Sambuc     *end_++ = i;
451*4684ddb6SLionel Sambuc }
452*4684ddb6SLionel Sambuc 
453*4684ddb6SLionel Sambuc // private api
454*4684ddb6SLionel Sambuc 
455*4684ddb6SLionel Sambuc _LIBCPP_HIDDEN
456*4684ddb6SLionel Sambuc __i_node*
457*4684ddb6SLionel Sambuc __libcpp_db::__insert_iterator(void* __i)
458*4684ddb6SLionel Sambuc {
459*4684ddb6SLionel Sambuc     if (__isz_ + 1 > static_cast<size_t>(__iend_ - __ibeg_))
460*4684ddb6SLionel Sambuc     {
461*4684ddb6SLionel Sambuc         size_t nc = __next_prime(2*static_cast<size_t>(__iend_ - __ibeg_) + 1);
462*4684ddb6SLionel Sambuc         __i_node** ibeg = static_cast<__i_node**>(calloc(nc, sizeof(void*)));
463*4684ddb6SLionel Sambuc         if (ibeg == nullptr)
464*4684ddb6SLionel Sambuc #ifndef _LIBCPP_NO_EXCEPTIONS
465*4684ddb6SLionel Sambuc             throw bad_alloc();
466*4684ddb6SLionel Sambuc #else
467*4684ddb6SLionel Sambuc             abort();
468*4684ddb6SLionel Sambuc #endif
469*4684ddb6SLionel Sambuc         for (__i_node** p = __ibeg_; p != __iend_; ++p)
470*4684ddb6SLionel Sambuc         {
471*4684ddb6SLionel Sambuc             __i_node* q = *p;
472*4684ddb6SLionel Sambuc             while (q != nullptr)
473*4684ddb6SLionel Sambuc             {
474*4684ddb6SLionel Sambuc                 size_t h = hash<void*>()(q->__i_) % nc;
475*4684ddb6SLionel Sambuc                 __i_node* r = q->__next_;
476*4684ddb6SLionel Sambuc                 q->__next_ = ibeg[h];
477*4684ddb6SLionel Sambuc                 ibeg[h] = q;
478*4684ddb6SLionel Sambuc                 q = r;
479*4684ddb6SLionel Sambuc             }
480*4684ddb6SLionel Sambuc         }
481*4684ddb6SLionel Sambuc         free(__ibeg_);
482*4684ddb6SLionel Sambuc         __ibeg_ = ibeg;
483*4684ddb6SLionel Sambuc         __iend_ = __ibeg_ + nc;
484*4684ddb6SLionel Sambuc     }
485*4684ddb6SLionel Sambuc     size_t hi = hash<void*>()(__i) % static_cast<size_t>(__iend_ - __ibeg_);
486*4684ddb6SLionel Sambuc     __i_node* p = __ibeg_[hi];
487*4684ddb6SLionel Sambuc     __i_node* r = __ibeg_[hi] =
488*4684ddb6SLionel Sambuc       static_cast<__i_node*>(malloc(sizeof(__i_node)));
489*4684ddb6SLionel Sambuc     if (r == nullptr)
490*4684ddb6SLionel Sambuc #ifndef _LIBCPP_NO_EXCEPTIONS
491*4684ddb6SLionel Sambuc         throw bad_alloc();
492*4684ddb6SLionel Sambuc #else
493*4684ddb6SLionel Sambuc         abort();
494*4684ddb6SLionel Sambuc #endif
495*4684ddb6SLionel Sambuc     ::new(r) __i_node(__i, p, nullptr);
496*4684ddb6SLionel Sambuc     ++__isz_;
497*4684ddb6SLionel Sambuc     return r;
498*4684ddb6SLionel Sambuc }
499*4684ddb6SLionel Sambuc 
500*4684ddb6SLionel Sambuc _LIBCPP_HIDDEN
501*4684ddb6SLionel Sambuc __i_node*
502*4684ddb6SLionel Sambuc __libcpp_db::__find_iterator(const void* __i) const
503*4684ddb6SLionel Sambuc {
504*4684ddb6SLionel Sambuc     __i_node* r = nullptr;
505*4684ddb6SLionel Sambuc     if (__ibeg_ != __iend_)
506*4684ddb6SLionel Sambuc     {
507*4684ddb6SLionel Sambuc         size_t h = hash<const void*>()(__i) % static_cast<size_t>(__iend_ - __ibeg_);
508*4684ddb6SLionel Sambuc         for (__i_node* nd = __ibeg_[h]; nd != nullptr; nd = nd->__next_)
509*4684ddb6SLionel Sambuc         {
510*4684ddb6SLionel Sambuc             if (nd->__i_ == __i)
511*4684ddb6SLionel Sambuc             {
512*4684ddb6SLionel Sambuc                 r = nd;
513*4684ddb6SLionel Sambuc                 break;
514*4684ddb6SLionel Sambuc             }
515*4684ddb6SLionel Sambuc         }
516*4684ddb6SLionel Sambuc     }
517*4684ddb6SLionel Sambuc     return r;
518*4684ddb6SLionel Sambuc }
519*4684ddb6SLionel Sambuc 
520*4684ddb6SLionel Sambuc _LIBCPP_HIDDEN
521*4684ddb6SLionel Sambuc void
522*4684ddb6SLionel Sambuc __c_node::__remove(__i_node* p)
523*4684ddb6SLionel Sambuc {
524*4684ddb6SLionel Sambuc     __i_node** r = find(beg_, end_, p);
525*4684ddb6SLionel Sambuc     _LIBCPP_ASSERT(r != end_, "debug mode internal logic error __c_node::__remove");
526*4684ddb6SLionel Sambuc     if (--end_ != r)
527*4684ddb6SLionel Sambuc         memmove(r, r+1, static_cast<size_t>(end_ - r)*sizeof(__i_node*));
528*4684ddb6SLionel Sambuc }
529*4684ddb6SLionel Sambuc 
530*4684ddb6SLionel Sambuc _LIBCPP_END_NAMESPACE_STD
531