| 3134 | |
| 3135 | private: |
| 3136 | static MemStats getFor(ConcurrentQueue* q) |
| 3137 | { |
| 3138 | MemStats stats = { 0 }; |
| 3139 | |
| 3140 | stats.elementsEnqueued = q->size_approx(); |
| 3141 | |
| 3142 | auto block = q->freeList.head_unsafe(); |
| 3143 | while (block != nullptr) { |
| 3144 | ++stats.allocatedBlocks; |
| 3145 | ++stats.freeBlocks; |
| 3146 | block = block->freeListNext.load(std::memory_order_relaxed); |
| 3147 | } |
| 3148 | |
| 3149 | for (auto ptr = q->producerListTail.load(std::memory_order_acquire); ptr != nullptr; ptr = ptr->next_prod()) { |
| 3150 | bool implicit = dynamic_cast<ImplicitProducer*>(ptr) != nullptr; |
| 3151 | stats.implicitProducers += implicit ? 1 : 0; |
| 3152 | stats.explicitProducers += implicit ? 0 : 1; |
| 3153 | |
| 3154 | if (implicit) { |
| 3155 | auto prod = static_cast<ImplicitProducer*>(ptr); |
| 3156 | stats.queueClassBytes += sizeof(ImplicitProducer); |
| 3157 | auto head = prod->headIndex.load(std::memory_order_relaxed); |
| 3158 | auto tail = prod->tailIndex.load(std::memory_order_relaxed); |
| 3159 | auto hash = prod->blockIndex.load(std::memory_order_relaxed); |
| 3160 | if (hash != nullptr) { |
| 3161 | for (size_t i = 0; i != hash->capacity; ++i) { |
| 3162 | if (hash->index[i]->key.load(std::memory_order_relaxed) != ImplicitProducer::INVALID_BLOCK_BASE && hash->index[i]->value.load(std::memory_order_relaxed) != nullptr) { |
| 3163 | ++stats.allocatedBlocks; |
| 3164 | ++stats.ownedBlocksImplicit; |
| 3165 | } |
| 3166 | } |
| 3167 | stats.implicitBlockIndexBytes += hash->capacity * sizeof(typename ImplicitProducer::BlockIndexEntry); |
| 3168 | for (; hash != nullptr; hash = hash->prev) { |
| 3169 | stats.implicitBlockIndexBytes += sizeof(typename ImplicitProducer::BlockIndexHeader) + hash->capacity * sizeof(typename ImplicitProducer::BlockIndexEntry*); |
| 3170 | } |
| 3171 | } |
| 3172 | for (; details::circular_less_than<index_t>(head, tail); head += BLOCK_SIZE) { |
| 3173 | //auto block = prod->get_block_index_entry_for_index(head); |
| 3174 | ++stats.usedBlocks; |
| 3175 | } |
| 3176 | } |
| 3177 | else { |
| 3178 | auto prod = static_cast<ExplicitProducer*>(ptr); |
| 3179 | stats.queueClassBytes += sizeof(ExplicitProducer); |
| 3180 | auto tailBlock = prod->tailBlock; |
| 3181 | bool wasNonEmpty = false; |
| 3182 | if (tailBlock != nullptr) { |
| 3183 | auto block = tailBlock; |
| 3184 | do { |
| 3185 | ++stats.allocatedBlocks; |
| 3186 | if (!block->ConcurrentQueue::Block::template is_empty<explicit_context>() || wasNonEmpty) { |
| 3187 | ++stats.usedBlocks; |
| 3188 | wasNonEmpty = wasNonEmpty || block != tailBlock; |
| 3189 | } |
| 3190 | ++stats.ownedBlocksExplicit; |
| 3191 | block = block->next; |
| 3192 | } while (block != tailBlock); |
| 3193 | } |
nothing calls this directly
no test coverage detected