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