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