1 //===-------------------------- 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 28 const __libcpp_db* 29 __get_const_db() 30 { 31 return __get_db(); 32 } 33 34 namespace 35 { 36 37 typedef mutex mutex_type; 38 // struct mutex_type 39 // { 40 // void lock() {} 41 // void unlock() {}; 42 // }; 43 typedef lock_guard<mutex_type> WLock; 44 typedef lock_guard<mutex_type> RLock; 45 46 mutex_type& 47 mut() 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 112 void* 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 120 void 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 175 void 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 206 void 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 240 void 241 __libcpp_db::unlock() const 242 { 243 mut().unlock(); 244 } 245 246 void 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 274 void 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 300 bool 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 308 bool 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 316 bool 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 324 bool 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 332 bool 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 343 void 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 431 void 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 453 void 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 463