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