1eb8650a7SLouis Dionne //===----------------------------------------------------------------------===// 2f554add5SHoward Hinnant // 357b08b09SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 457b08b09SChandler Carruth // See https://llvm.org/LICENSE.txt for license information. 557b08b09SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6f554add5SHoward Hinnant // 7f554add5SHoward Hinnant //===----------------------------------------------------------------------===// 8f554add5SHoward Hinnant 9*bbb0f2c7SArthur O'Dwyer #include <__config> 10*bbb0f2c7SArthur O'Dwyer #include <__debug> 11*bbb0f2c7SArthur O'Dwyer #include <__hash_table> 12*bbb0f2c7SArthur O'Dwyer #include <algorithm> 13*bbb0f2c7SArthur O'Dwyer #include <cstdio> 14*bbb0f2c7SArthur O'Dwyer #include <functional> 15*bbb0f2c7SArthur O'Dwyer #include <string> 16*bbb0f2c7SArthur O'Dwyer 17996e62eeSPetr Hosek #ifndef _LIBCPP_HAS_NO_THREADS 18*bbb0f2c7SArthur O'Dwyer # include <mutex> 19a9b5fff5SMichał Górny # if defined(__ELF__) && defined(_LIBCPP_LINK_PTHREAD_LIB) 20996e62eeSPetr Hosek # pragma comment(lib, "pthread") 21996e62eeSPetr Hosek # endif 22996e62eeSPetr Hosek #endif 23f554add5SHoward Hinnant 24f554add5SHoward Hinnant _LIBCPP_BEGIN_NAMESPACE_STD 25f554add5SHoward Hinnant 2661b302f9SEric Fiselier std::string __libcpp_debug_info::what() const { 2761b302f9SEric Fiselier string msg = __file_; 2861b302f9SEric Fiselier msg += ":" + to_string(__line_) + ": _LIBCPP_ASSERT '"; 2961b302f9SEric Fiselier msg += __pred_; 30687d3213SEric Fiselier msg += "' failed. "; 3161b302f9SEric Fiselier msg += __msg_; 32687d3213SEric Fiselier return msg; 33687d3213SEric Fiselier } 3461b302f9SEric Fiselier _LIBCPP_NORETURN void __libcpp_abort_debug_function(__libcpp_debug_info const& info) { 3561b302f9SEric Fiselier std::fprintf(stderr, "%s\n", info.what().c_str()); 3661b302f9SEric Fiselier std::abort(); 3761b302f9SEric Fiselier } 38687d3213SEric Fiselier 3905337a75SArthur O'Dwyer constinit __libcpp_debug_function_type __libcpp_debug_function = __libcpp_abort_debug_function; 40687d3213SEric Fiselier 41687d3213SEric Fiselier bool __libcpp_set_debug_function(__libcpp_debug_function_type __func) { 42687d3213SEric Fiselier __libcpp_debug_function = __func; 43687d3213SEric Fiselier return true; 44687d3213SEric Fiselier } 45687d3213SEric Fiselier 466e41256fSHoward Hinnant _LIBCPP_FUNC_VIS 47f554add5SHoward Hinnant __libcpp_db* 48f554add5SHoward Hinnant __get_db() 49f554add5SHoward Hinnant { 5081875a67SLouis Dionne static _LIBCPP_NO_DESTROY __libcpp_db db; 51f554add5SHoward Hinnant return &db; 52267e3e1eSHoward Hinnant } 53f554add5SHoward Hinnant 546e41256fSHoward Hinnant _LIBCPP_FUNC_VIS 55f554add5SHoward Hinnant const __libcpp_db* 56f554add5SHoward Hinnant __get_const_db() 57f554add5SHoward Hinnant { 58f554add5SHoward Hinnant return __get_db(); 59f554add5SHoward Hinnant } 60f554add5SHoward Hinnant 61f554add5SHoward Hinnant namespace 62f554add5SHoward Hinnant { 63f554add5SHoward Hinnant 64b3fcc67fSJonathan Roelofs #ifndef _LIBCPP_HAS_NO_THREADS 65f554add5SHoward Hinnant typedef mutex mutex_type; 66f554add5SHoward Hinnant typedef lock_guard<mutex_type> WLock; 67f554add5SHoward Hinnant typedef lock_guard<mutex_type> RLock; 68f554add5SHoward Hinnant 69f554add5SHoward Hinnant mutex_type& 70f554add5SHoward Hinnant mut() 71f554add5SHoward Hinnant { 7281875a67SLouis Dionne static _LIBCPP_NO_DESTROY mutex_type m; 73f554add5SHoward Hinnant return m; 74f554add5SHoward Hinnant } 75b3fcc67fSJonathan Roelofs #endif // !_LIBCPP_HAS_NO_THREADS 76f554add5SHoward Hinnant 77f554add5SHoward Hinnant } // unnamed namespace 78f554add5SHoward Hinnant 79f554add5SHoward Hinnant __i_node::~__i_node() 80f554add5SHoward Hinnant { 81f554add5SHoward Hinnant if (__next_) 82f554add5SHoward Hinnant { 83f554add5SHoward Hinnant __next_->~__i_node(); 84f554add5SHoward Hinnant free(__next_); 85f554add5SHoward Hinnant } 86f554add5SHoward Hinnant } 87f554add5SHoward Hinnant 88f554add5SHoward Hinnant __c_node::~__c_node() 89f554add5SHoward Hinnant { 90f554add5SHoward Hinnant free(beg_); 91f554add5SHoward Hinnant if (__next_) 92f554add5SHoward Hinnant { 93f554add5SHoward Hinnant __next_->~__c_node(); 94f554add5SHoward Hinnant free(__next_); 95f554add5SHoward Hinnant } 96f554add5SHoward Hinnant } 97f554add5SHoward Hinnant 98f554add5SHoward Hinnant __libcpp_db::__libcpp_db() 99f554add5SHoward Hinnant : __cbeg_(nullptr), 100f554add5SHoward Hinnant __cend_(nullptr), 101f554add5SHoward Hinnant __csz_(0), 102f554add5SHoward Hinnant __ibeg_(nullptr), 103f554add5SHoward Hinnant __iend_(nullptr), 104f554add5SHoward Hinnant __isz_(0) 105f554add5SHoward Hinnant { 106f554add5SHoward Hinnant } 107f554add5SHoward Hinnant 108f554add5SHoward Hinnant __libcpp_db::~__libcpp_db() 109f554add5SHoward Hinnant { 110f554add5SHoward Hinnant if (__cbeg_) 111f554add5SHoward Hinnant { 112f554add5SHoward Hinnant for (__c_node** p = __cbeg_; p != __cend_; ++p) 113f554add5SHoward Hinnant { 114f554add5SHoward Hinnant if (*p != nullptr) 115f554add5SHoward Hinnant { 116f554add5SHoward Hinnant (*p)->~__c_node(); 117f554add5SHoward Hinnant free(*p); 118f554add5SHoward Hinnant } 119f554add5SHoward Hinnant } 120f554add5SHoward Hinnant free(__cbeg_); 121f554add5SHoward Hinnant } 122f554add5SHoward Hinnant if (__ibeg_) 123f554add5SHoward Hinnant { 124f554add5SHoward Hinnant for (__i_node** p = __ibeg_; p != __iend_; ++p) 125f554add5SHoward Hinnant { 126f554add5SHoward Hinnant if (*p != nullptr) 127f554add5SHoward Hinnant { 128f554add5SHoward Hinnant (*p)->~__i_node(); 129f554add5SHoward Hinnant free(*p); 130f554add5SHoward Hinnant } 131f554add5SHoward Hinnant } 132f554add5SHoward Hinnant free(__ibeg_); 133f554add5SHoward Hinnant } 134f554add5SHoward Hinnant } 135f554add5SHoward Hinnant 136f554add5SHoward Hinnant void* 137f554add5SHoward Hinnant __libcpp_db::__find_c_from_i(void* __i) const 138f554add5SHoward Hinnant { 139b3fcc67fSJonathan Roelofs #ifndef _LIBCPP_HAS_NO_THREADS 140f554add5SHoward Hinnant RLock _(mut()); 141b3fcc67fSJonathan Roelofs #endif 142f554add5SHoward Hinnant __i_node* i = __find_iterator(__i); 143f7509231SHoward Hinnant _LIBCPP_ASSERT(i != nullptr, "iterator not found in debug database."); 144c36bfc49SHoward Hinnant return i->__c_ != nullptr ? i->__c_->__c_ : nullptr; 145f554add5SHoward Hinnant } 146f554add5SHoward Hinnant 147f554add5SHoward Hinnant void 148f554add5SHoward Hinnant __libcpp_db::__insert_ic(void* __i, const void* __c) 149f554add5SHoward Hinnant { 150b3fcc67fSJonathan Roelofs #ifndef _LIBCPP_HAS_NO_THREADS 151f554add5SHoward Hinnant WLock _(mut()); 152b3fcc67fSJonathan Roelofs #endif 153fc88dbd2SHoward Hinnant if (__cbeg_ == __cend_) 154fc88dbd2SHoward Hinnant return; 155c206366fSHoward Hinnant size_t hc = hash<const void*>()(__c) % static_cast<size_t>(__cend_ - __cbeg_); 156f554add5SHoward Hinnant __c_node* c = __cbeg_[hc]; 157fc88dbd2SHoward Hinnant if (c == nullptr) 158fc88dbd2SHoward Hinnant return; 159f554add5SHoward Hinnant while (c->__c_ != __c) 160f554add5SHoward Hinnant { 161f554add5SHoward Hinnant c = c->__next_; 162fc88dbd2SHoward Hinnant if (c == nullptr) 163fc88dbd2SHoward Hinnant return; 164f554add5SHoward Hinnant } 165fc88dbd2SHoward Hinnant __i_node* i = __insert_iterator(__i); 166f554add5SHoward Hinnant c->__add(i); 167f554add5SHoward Hinnant i->__c_ = c; 168f554add5SHoward Hinnant } 169f554add5SHoward Hinnant 1701c014d75SEric Fiselier void 1711c014d75SEric Fiselier __libcpp_db::__insert_c(void* __c, __libcpp_db::_InsertConstruct *__fn) 172f554add5SHoward Hinnant { 173b3fcc67fSJonathan Roelofs #ifndef _LIBCPP_HAS_NO_THREADS 174f554add5SHoward Hinnant WLock _(mut()); 175b3fcc67fSJonathan Roelofs #endif 176c206366fSHoward Hinnant if (__csz_ + 1 > static_cast<size_t>(__cend_ - __cbeg_)) 177f554add5SHoward Hinnant { 178c206366fSHoward Hinnant size_t nc = __next_prime(2*static_cast<size_t>(__cend_ - __cbeg_) + 1); 179cb843f5bSLouis Dionne __c_node** cbeg = static_cast<__c_node**>(calloc(nc, sizeof(__c_node*))); 180f554add5SHoward Hinnant if (cbeg == nullptr) 181d437fa5cSMarshall Clow __throw_bad_alloc(); 182d437fa5cSMarshall Clow 183f554add5SHoward Hinnant for (__c_node** p = __cbeg_; p != __cend_; ++p) 184f554add5SHoward Hinnant { 185f554add5SHoward Hinnant __c_node* q = *p; 186f554add5SHoward Hinnant while (q != nullptr) 187f554add5SHoward Hinnant { 188f554add5SHoward Hinnant size_t h = hash<void*>()(q->__c_) % nc; 189f554add5SHoward Hinnant __c_node* r = q->__next_; 190f554add5SHoward Hinnant q->__next_ = cbeg[h]; 191f554add5SHoward Hinnant cbeg[h] = q; 192f554add5SHoward Hinnant q = r; 193f554add5SHoward Hinnant } 194f554add5SHoward Hinnant } 195f554add5SHoward Hinnant free(__cbeg_); 196f554add5SHoward Hinnant __cbeg_ = cbeg; 197f554add5SHoward Hinnant __cend_ = __cbeg_ + nc; 198f554add5SHoward Hinnant } 199c206366fSHoward Hinnant size_t hc = hash<void*>()(__c) % static_cast<size_t>(__cend_ - __cbeg_); 200f554add5SHoward Hinnant __c_node* p = __cbeg_[hc]; 2011c014d75SEric Fiselier void *buf = malloc(sizeof(__c_node)); 2021c014d75SEric Fiselier if (buf == nullptr) 203d437fa5cSMarshall Clow __throw_bad_alloc(); 2041c014d75SEric Fiselier __cbeg_[hc] = __fn(buf, __c, p); 205d437fa5cSMarshall Clow 206f554add5SHoward Hinnant ++__csz_; 207f554add5SHoward Hinnant } 208f554add5SHoward Hinnant 209f554add5SHoward Hinnant void 210f554add5SHoward Hinnant __libcpp_db::__erase_i(void* __i) 211f554add5SHoward Hinnant { 212b3fcc67fSJonathan Roelofs #ifndef _LIBCPP_HAS_NO_THREADS 213f554add5SHoward Hinnant WLock _(mut()); 214b3fcc67fSJonathan Roelofs #endif 215f554add5SHoward Hinnant if (__ibeg_ != __iend_) 216f554add5SHoward Hinnant { 217c206366fSHoward Hinnant size_t hi = hash<void*>()(__i) % static_cast<size_t>(__iend_ - __ibeg_); 218f554add5SHoward Hinnant __i_node* p = __ibeg_[hi]; 219f554add5SHoward Hinnant if (p != nullptr) 220f554add5SHoward Hinnant { 221f554add5SHoward Hinnant __i_node* q = nullptr; 222f554add5SHoward Hinnant while (p->__i_ != __i) 223f554add5SHoward Hinnant { 224f554add5SHoward Hinnant q = p; 225f554add5SHoward Hinnant p = p->__next_; 226f554add5SHoward Hinnant if (p == nullptr) 227f554add5SHoward Hinnant return; 228f554add5SHoward Hinnant } 229f554add5SHoward Hinnant if (q == nullptr) 230f554add5SHoward Hinnant __ibeg_[hi] = p->__next_; 231f554add5SHoward Hinnant else 232f554add5SHoward Hinnant q->__next_ = p->__next_; 233f554add5SHoward Hinnant __c_node* c = p->__c_; 234f554add5SHoward Hinnant --__isz_; 235f554add5SHoward Hinnant if (c != nullptr) 236f554add5SHoward Hinnant c->__remove(p); 23761bff619SEric Fiselier free(p); 238f554add5SHoward Hinnant } 239f554add5SHoward Hinnant } 240f554add5SHoward Hinnant } 241f554add5SHoward Hinnant 242f554add5SHoward Hinnant void 243f554add5SHoward Hinnant __libcpp_db::__invalidate_all(void* __c) 244f554add5SHoward Hinnant { 245b3fcc67fSJonathan Roelofs #ifndef _LIBCPP_HAS_NO_THREADS 246f554add5SHoward Hinnant WLock _(mut()); 247b3fcc67fSJonathan Roelofs #endif 248fc88dbd2SHoward Hinnant if (__cend_ != __cbeg_) 249fc88dbd2SHoward Hinnant { 250c206366fSHoward Hinnant size_t hc = hash<void*>()(__c) % static_cast<size_t>(__cend_ - __cbeg_); 251f554add5SHoward Hinnant __c_node* p = __cbeg_[hc]; 252fc88dbd2SHoward Hinnant if (p == nullptr) 253fc88dbd2SHoward Hinnant return; 254f554add5SHoward Hinnant while (p->__c_ != __c) 255f554add5SHoward Hinnant { 256f554add5SHoward Hinnant p = p->__next_; 257fc88dbd2SHoward Hinnant if (p == nullptr) 258fc88dbd2SHoward Hinnant return; 259f554add5SHoward Hinnant } 260f554add5SHoward Hinnant while (p->end_ != p->beg_) 261f554add5SHoward Hinnant { 262f554add5SHoward Hinnant --p->end_; 263f554add5SHoward Hinnant (*p->end_)->__c_ = nullptr; 264f554add5SHoward Hinnant } 265f554add5SHoward Hinnant } 266fc88dbd2SHoward Hinnant } 267f554add5SHoward Hinnant 268f554add5SHoward Hinnant __c_node* 269f554add5SHoward Hinnant __libcpp_db::__find_c_and_lock(void* __c) const 270f554add5SHoward Hinnant { 271b3fcc67fSJonathan Roelofs #ifndef _LIBCPP_HAS_NO_THREADS 272f554add5SHoward Hinnant mut().lock(); 273b3fcc67fSJonathan Roelofs #endif 274fc88dbd2SHoward Hinnant if (__cend_ == __cbeg_) 275fc88dbd2SHoward Hinnant { 276b3fcc67fSJonathan Roelofs #ifndef _LIBCPP_HAS_NO_THREADS 277fc88dbd2SHoward Hinnant mut().unlock(); 278b3fcc67fSJonathan Roelofs #endif 279fc88dbd2SHoward Hinnant return nullptr; 280fc88dbd2SHoward Hinnant } 281c206366fSHoward Hinnant size_t hc = hash<void*>()(__c) % static_cast<size_t>(__cend_ - __cbeg_); 282f554add5SHoward Hinnant __c_node* p = __cbeg_[hc]; 283fc88dbd2SHoward Hinnant if (p == nullptr) 284fc88dbd2SHoward Hinnant { 285b3fcc67fSJonathan Roelofs #ifndef _LIBCPP_HAS_NO_THREADS 286fc88dbd2SHoward Hinnant mut().unlock(); 287b3fcc67fSJonathan Roelofs #endif 288fc88dbd2SHoward Hinnant return nullptr; 289fc88dbd2SHoward Hinnant } 290f554add5SHoward Hinnant while (p->__c_ != __c) 291f554add5SHoward Hinnant { 292f554add5SHoward Hinnant p = p->__next_; 293fc88dbd2SHoward Hinnant if (p == nullptr) 294fc88dbd2SHoward Hinnant { 295b3fcc67fSJonathan Roelofs #ifndef _LIBCPP_HAS_NO_THREADS 296fc88dbd2SHoward Hinnant mut().unlock(); 297b3fcc67fSJonathan Roelofs #endif 298fc88dbd2SHoward Hinnant return nullptr; 299fc88dbd2SHoward Hinnant } 300f554add5SHoward Hinnant } 301f554add5SHoward Hinnant return p; 302f554add5SHoward Hinnant } 303f554add5SHoward Hinnant 304920b56caSHoward Hinnant __c_node* 305920b56caSHoward Hinnant __libcpp_db::__find_c(void* __c) const 306920b56caSHoward Hinnant { 307c206366fSHoward Hinnant size_t hc = hash<void*>()(__c) % static_cast<size_t>(__cend_ - __cbeg_); 308920b56caSHoward Hinnant __c_node* p = __cbeg_[hc]; 309920b56caSHoward Hinnant _LIBCPP_ASSERT(p != nullptr, "debug mode internal logic error __find_c A"); 310920b56caSHoward Hinnant while (p->__c_ != __c) 311920b56caSHoward Hinnant { 312920b56caSHoward Hinnant p = p->__next_; 313920b56caSHoward Hinnant _LIBCPP_ASSERT(p != nullptr, "debug mode internal logic error __find_c B"); 314920b56caSHoward Hinnant } 315920b56caSHoward Hinnant return p; 316920b56caSHoward Hinnant } 317920b56caSHoward Hinnant 318f554add5SHoward Hinnant void 319f554add5SHoward Hinnant __libcpp_db::unlock() const 320f554add5SHoward Hinnant { 321b3fcc67fSJonathan Roelofs #ifndef _LIBCPP_HAS_NO_THREADS 322f554add5SHoward Hinnant mut().unlock(); 323b3fcc67fSJonathan Roelofs #endif 324f554add5SHoward Hinnant } 325f554add5SHoward Hinnant 326f554add5SHoward Hinnant void 327f554add5SHoward Hinnant __libcpp_db::__erase_c(void* __c) 328f554add5SHoward Hinnant { 329b3fcc67fSJonathan Roelofs #ifndef _LIBCPP_HAS_NO_THREADS 330f554add5SHoward Hinnant WLock _(mut()); 331b3fcc67fSJonathan Roelofs #endif 332fc88dbd2SHoward Hinnant if (__cend_ != __cbeg_) 333fc88dbd2SHoward Hinnant { 334c206366fSHoward Hinnant size_t hc = hash<void*>()(__c) % static_cast<size_t>(__cend_ - __cbeg_); 335f554add5SHoward Hinnant __c_node* p = __cbeg_[hc]; 336fc88dbd2SHoward Hinnant if (p == nullptr) 337fc88dbd2SHoward Hinnant return; 338f554add5SHoward Hinnant __c_node* q = nullptr; 339f554add5SHoward Hinnant _LIBCPP_ASSERT(p != nullptr, "debug mode internal logic error __erase_c A"); 340f554add5SHoward Hinnant while (p->__c_ != __c) 341f554add5SHoward Hinnant { 342f554add5SHoward Hinnant q = p; 343f554add5SHoward Hinnant p = p->__next_; 344fc88dbd2SHoward Hinnant if (p == nullptr) 345fc88dbd2SHoward Hinnant return; 346f554add5SHoward Hinnant _LIBCPP_ASSERT(p != nullptr, "debug mode internal logic error __erase_c B"); 347f554add5SHoward Hinnant } 348f554add5SHoward Hinnant if (q == nullptr) 349f554add5SHoward Hinnant __cbeg_[hc] = p->__next_; 350f554add5SHoward Hinnant else 351f554add5SHoward Hinnant q->__next_ = p->__next_; 352f554add5SHoward Hinnant while (p->end_ != p->beg_) 353f554add5SHoward Hinnant { 354f554add5SHoward Hinnant --p->end_; 355f554add5SHoward Hinnant (*p->end_)->__c_ = nullptr; 356f554add5SHoward Hinnant } 357f554add5SHoward Hinnant free(p->beg_); 358f554add5SHoward Hinnant free(p); 359f554add5SHoward Hinnant --__csz_; 360f554add5SHoward Hinnant } 361fc88dbd2SHoward Hinnant } 362f554add5SHoward Hinnant 363f554add5SHoward Hinnant void 364f554add5SHoward Hinnant __libcpp_db::__iterator_copy(void* __i, const void* __i0) 365f554add5SHoward Hinnant { 366b3fcc67fSJonathan Roelofs #ifndef _LIBCPP_HAS_NO_THREADS 367f554add5SHoward Hinnant WLock _(mut()); 368b3fcc67fSJonathan Roelofs #endif 369f554add5SHoward Hinnant __i_node* i = __find_iterator(__i); 370f554add5SHoward Hinnant __i_node* i0 = __find_iterator(__i0); 371f554add5SHoward Hinnant __c_node* c0 = i0 != nullptr ? i0->__c_ : nullptr; 372f7509231SHoward Hinnant if (i == nullptr && i0 != nullptr) 373f554add5SHoward Hinnant i = __insert_iterator(__i); 374f554add5SHoward Hinnant __c_node* c = i != nullptr ? i->__c_ : nullptr; 375f554add5SHoward Hinnant if (c != c0) 376f554add5SHoward Hinnant { 377f554add5SHoward Hinnant if (c != nullptr) 378f554add5SHoward Hinnant c->__remove(i); 379f554add5SHoward Hinnant if (i != nullptr) 380f554add5SHoward Hinnant { 381f554add5SHoward Hinnant i->__c_ = nullptr; 382f554add5SHoward Hinnant if (c0 != nullptr) 383f554add5SHoward Hinnant { 384f554add5SHoward Hinnant i->__c_ = c0; 385f554add5SHoward Hinnant i->__c_->__add(i); 386f554add5SHoward Hinnant } 387f554add5SHoward Hinnant } 388f554add5SHoward Hinnant } 389f554add5SHoward Hinnant } 390f554add5SHoward Hinnant 391f554add5SHoward Hinnant bool 392f554add5SHoward Hinnant __libcpp_db::__dereferenceable(const void* __i) const 393f554add5SHoward Hinnant { 394b3fcc67fSJonathan Roelofs #ifndef _LIBCPP_HAS_NO_THREADS 395f554add5SHoward Hinnant RLock _(mut()); 396b3fcc67fSJonathan Roelofs #endif 397f554add5SHoward Hinnant __i_node* i = __find_iterator(__i); 398f554add5SHoward Hinnant return i != nullptr && i->__c_ != nullptr && i->__c_->__dereferenceable(__i); 399f554add5SHoward Hinnant } 400f554add5SHoward Hinnant 401f554add5SHoward Hinnant bool 402f554add5SHoward Hinnant __libcpp_db::__decrementable(const void* __i) const 403f554add5SHoward Hinnant { 404b3fcc67fSJonathan Roelofs #ifndef _LIBCPP_HAS_NO_THREADS 405f554add5SHoward Hinnant RLock _(mut()); 406b3fcc67fSJonathan Roelofs #endif 407f554add5SHoward Hinnant __i_node* i = __find_iterator(__i); 408f554add5SHoward Hinnant return i != nullptr && i->__c_ != nullptr && i->__c_->__decrementable(__i); 409f554add5SHoward Hinnant } 410f554add5SHoward Hinnant 411f554add5SHoward Hinnant bool 412f554add5SHoward Hinnant __libcpp_db::__addable(const void* __i, ptrdiff_t __n) const 413f554add5SHoward Hinnant { 414b3fcc67fSJonathan Roelofs #ifndef _LIBCPP_HAS_NO_THREADS 415f554add5SHoward Hinnant RLock _(mut()); 416b3fcc67fSJonathan Roelofs #endif 417f554add5SHoward Hinnant __i_node* i = __find_iterator(__i); 418f554add5SHoward Hinnant return i != nullptr && i->__c_ != nullptr && i->__c_->__addable(__i, __n); 419f554add5SHoward Hinnant } 420f554add5SHoward Hinnant 421f554add5SHoward Hinnant bool 422f554add5SHoward Hinnant __libcpp_db::__subscriptable(const void* __i, ptrdiff_t __n) const 423f554add5SHoward Hinnant { 424b3fcc67fSJonathan Roelofs #ifndef _LIBCPP_HAS_NO_THREADS 425f554add5SHoward Hinnant RLock _(mut()); 426b3fcc67fSJonathan Roelofs #endif 427f554add5SHoward Hinnant __i_node* i = __find_iterator(__i); 428f554add5SHoward Hinnant return i != nullptr && i->__c_ != nullptr && i->__c_->__subscriptable(__i, __n); 429f554add5SHoward Hinnant } 430f554add5SHoward Hinnant 431f554add5SHoward Hinnant bool 43242a3046eSHoward Hinnant __libcpp_db::__less_than_comparable(const void* __i, const void* __j) const 433f554add5SHoward Hinnant { 434b3fcc67fSJonathan Roelofs #ifndef _LIBCPP_HAS_NO_THREADS 435f554add5SHoward Hinnant RLock _(mut()); 436b3fcc67fSJonathan Roelofs #endif 437f554add5SHoward Hinnant __i_node* i = __find_iterator(__i); 438f554add5SHoward Hinnant __i_node* j = __find_iterator(__j); 439f554add5SHoward Hinnant __c_node* ci = i != nullptr ? i->__c_ : nullptr; 440f554add5SHoward Hinnant __c_node* cj = j != nullptr ? j->__c_ : nullptr; 441bbc6893bSArthur O'Dwyer return ci == cj; 442f554add5SHoward Hinnant } 443f554add5SHoward Hinnant 444f554add5SHoward Hinnant void 445f554add5SHoward Hinnant __libcpp_db::swap(void* c1, void* c2) 446f554add5SHoward Hinnant { 447b3fcc67fSJonathan Roelofs #ifndef _LIBCPP_HAS_NO_THREADS 448f554add5SHoward Hinnant WLock _(mut()); 449b3fcc67fSJonathan Roelofs #endif 450c206366fSHoward Hinnant size_t hc = hash<void*>()(c1) % static_cast<size_t>(__cend_ - __cbeg_); 451f554add5SHoward Hinnant __c_node* p1 = __cbeg_[hc]; 452f554add5SHoward Hinnant _LIBCPP_ASSERT(p1 != nullptr, "debug mode internal logic error swap A"); 453f554add5SHoward Hinnant while (p1->__c_ != c1) 454f554add5SHoward Hinnant { 455f554add5SHoward Hinnant p1 = p1->__next_; 456f554add5SHoward Hinnant _LIBCPP_ASSERT(p1 != nullptr, "debug mode internal logic error swap B"); 457f554add5SHoward Hinnant } 458c206366fSHoward Hinnant hc = hash<void*>()(c2) % static_cast<size_t>(__cend_ - __cbeg_); 459f554add5SHoward Hinnant __c_node* p2 = __cbeg_[hc]; 460f554add5SHoward Hinnant _LIBCPP_ASSERT(p2 != nullptr, "debug mode internal logic error swap C"); 461f554add5SHoward Hinnant while (p2->__c_ != c2) 462f554add5SHoward Hinnant { 463f554add5SHoward Hinnant p2 = p2->__next_; 464f554add5SHoward Hinnant _LIBCPP_ASSERT(p2 != nullptr, "debug mode internal logic error swap D"); 465f554add5SHoward Hinnant } 466f554add5SHoward Hinnant std::swap(p1->beg_, p2->beg_); 467f554add5SHoward Hinnant std::swap(p1->end_, p2->end_); 468f554add5SHoward Hinnant std::swap(p1->cap_, p2->cap_); 469f554add5SHoward Hinnant for (__i_node** p = p1->beg_; p != p1->end_; ++p) 470f554add5SHoward Hinnant (*p)->__c_ = p1; 471f554add5SHoward Hinnant for (__i_node** p = p2->beg_; p != p2->end_; ++p) 472f554add5SHoward Hinnant (*p)->__c_ = p2; 473f554add5SHoward Hinnant } 474f554add5SHoward Hinnant 475c36bfc49SHoward Hinnant void 476c36bfc49SHoward Hinnant __libcpp_db::__insert_i(void* __i) 477c36bfc49SHoward Hinnant { 478b3fcc67fSJonathan Roelofs #ifndef _LIBCPP_HAS_NO_THREADS 479c36bfc49SHoward Hinnant WLock _(mut()); 480b3fcc67fSJonathan Roelofs #endif 481c36bfc49SHoward Hinnant __insert_iterator(__i); 482c36bfc49SHoward Hinnant } 483c36bfc49SHoward Hinnant 484920b56caSHoward Hinnant void 485920b56caSHoward Hinnant __c_node::__add(__i_node* i) 486920b56caSHoward Hinnant { 487920b56caSHoward Hinnant if (end_ == cap_) 488920b56caSHoward Hinnant { 489c206366fSHoward Hinnant size_t nc = 2*static_cast<size_t>(cap_ - beg_); 490920b56caSHoward Hinnant if (nc == 0) 491920b56caSHoward Hinnant nc = 1; 49285ad6c99SJoerg Sonnenberger __i_node** beg = 49385ad6c99SJoerg Sonnenberger static_cast<__i_node**>(malloc(nc * sizeof(__i_node*))); 494920b56caSHoward Hinnant if (beg == nullptr) 495d437fa5cSMarshall Clow __throw_bad_alloc(); 496d437fa5cSMarshall Clow 497920b56caSHoward Hinnant if (nc > 1) 498920b56caSHoward Hinnant memcpy(beg, beg_, nc/2*sizeof(__i_node*)); 499920b56caSHoward Hinnant free(beg_); 500920b56caSHoward Hinnant beg_ = beg; 501920b56caSHoward Hinnant end_ = beg_ + nc/2; 502920b56caSHoward Hinnant cap_ = beg_ + nc; 503920b56caSHoward Hinnant } 504920b56caSHoward Hinnant *end_++ = i; 505920b56caSHoward Hinnant } 506920b56caSHoward Hinnant 507f554add5SHoward Hinnant // private api 508f554add5SHoward Hinnant 509f554add5SHoward Hinnant _LIBCPP_HIDDEN 510f554add5SHoward Hinnant __i_node* 511f554add5SHoward Hinnant __libcpp_db::__insert_iterator(void* __i) 512f554add5SHoward Hinnant { 513c206366fSHoward Hinnant if (__isz_ + 1 > static_cast<size_t>(__iend_ - __ibeg_)) 514f554add5SHoward Hinnant { 515c206366fSHoward Hinnant size_t nc = __next_prime(2*static_cast<size_t>(__iend_ - __ibeg_) + 1); 516cb843f5bSLouis Dionne __i_node** ibeg = static_cast<__i_node**>(calloc(nc, sizeof(__i_node*))); 517f554add5SHoward Hinnant if (ibeg == nullptr) 518d437fa5cSMarshall Clow __throw_bad_alloc(); 519d437fa5cSMarshall Clow 520f554add5SHoward Hinnant for (__i_node** p = __ibeg_; p != __iend_; ++p) 521f554add5SHoward Hinnant { 522f554add5SHoward Hinnant __i_node* q = *p; 523f554add5SHoward Hinnant while (q != nullptr) 524f554add5SHoward Hinnant { 525f554add5SHoward Hinnant size_t h = hash<void*>()(q->__i_) % nc; 526f554add5SHoward Hinnant __i_node* r = q->__next_; 527f554add5SHoward Hinnant q->__next_ = ibeg[h]; 528f554add5SHoward Hinnant ibeg[h] = q; 529f554add5SHoward Hinnant q = r; 530f554add5SHoward Hinnant } 531f554add5SHoward Hinnant } 532f554add5SHoward Hinnant free(__ibeg_); 533f554add5SHoward Hinnant __ibeg_ = ibeg; 534f554add5SHoward Hinnant __iend_ = __ibeg_ + nc; 535f554add5SHoward Hinnant } 536c206366fSHoward Hinnant size_t hi = hash<void*>()(__i) % static_cast<size_t>(__iend_ - __ibeg_); 537f554add5SHoward Hinnant __i_node* p = __ibeg_[hi]; 53885ad6c99SJoerg Sonnenberger __i_node* r = __ibeg_[hi] = 53985ad6c99SJoerg Sonnenberger static_cast<__i_node*>(malloc(sizeof(__i_node))); 540f554add5SHoward Hinnant if (r == nullptr) 541d437fa5cSMarshall Clow __throw_bad_alloc(); 542d437fa5cSMarshall Clow 543f554add5SHoward Hinnant ::new(r) __i_node(__i, p, nullptr); 544f554add5SHoward Hinnant ++__isz_; 545f554add5SHoward Hinnant return r; 546f554add5SHoward Hinnant } 547f554add5SHoward Hinnant 548f554add5SHoward Hinnant _LIBCPP_HIDDEN 549f554add5SHoward Hinnant __i_node* 550f554add5SHoward Hinnant __libcpp_db::__find_iterator(const void* __i) const 551f554add5SHoward Hinnant { 552f554add5SHoward Hinnant __i_node* r = nullptr; 553f554add5SHoward Hinnant if (__ibeg_ != __iend_) 554f554add5SHoward Hinnant { 555c206366fSHoward Hinnant size_t h = hash<const void*>()(__i) % static_cast<size_t>(__iend_ - __ibeg_); 556f554add5SHoward Hinnant for (__i_node* nd = __ibeg_[h]; nd != nullptr; nd = nd->__next_) 557f554add5SHoward Hinnant { 558f554add5SHoward Hinnant if (nd->__i_ == __i) 559f554add5SHoward Hinnant { 560f554add5SHoward Hinnant r = nd; 561f554add5SHoward Hinnant break; 562f554add5SHoward Hinnant } 563f554add5SHoward Hinnant } 564f554add5SHoward Hinnant } 565f554add5SHoward Hinnant return r; 566f554add5SHoward Hinnant } 567f554add5SHoward Hinnant 568f554add5SHoward Hinnant _LIBCPP_HIDDEN 569f554add5SHoward Hinnant void 570f554add5SHoward Hinnant __c_node::__remove(__i_node* p) 571f554add5SHoward Hinnant { 572f554add5SHoward Hinnant __i_node** r = find(beg_, end_, p); 573f554add5SHoward Hinnant _LIBCPP_ASSERT(r != end_, "debug mode internal logic error __c_node::__remove"); 574f554add5SHoward Hinnant if (--end_ != r) 575c206366fSHoward Hinnant memmove(r, r+1, static_cast<size_t>(end_ - r)*sizeof(__i_node*)); 576f554add5SHoward Hinnant } 577f554add5SHoward Hinnant 578f554add5SHoward Hinnant _LIBCPP_END_NAMESPACE_STD 579