| 457 | } |
| 458 | |
| 459 | void LoggerBackend::CleanUpInvalidatedThreadContexts() noexcept |
| 460 | { |
| 461 | ThreadContextManager& threadManager = ThreadContextManager::Get(); |
| 462 | |
| 463 | if (!threadManager.HasInvalidThreadContext()) { |
| 464 | return; |
| 465 | } |
| 466 | |
| 467 | auto findInvalidAndEmptyThreadContextCallback = [](ThreadContext* threadContext) { |
| 468 | // If the thread context is invalid, it means the thread that created it has now died. |
| 469 | // We also want to empty the queue from all LogRecords before removing the thread context |
| 470 | if (!threadContext->IsValid()) { |
| 471 | DEATH_DEBUG_ASSERT(threadContext->HasUnboundedQueueType() || threadContext->HasBoundedQueueType()); |
| 472 | |
| 473 | if (threadContext->HasUnboundedQueueType()) { |
| 474 | return threadContext->GetSpscQueueUnion().UnboundedSpscQueue.empty() && |
| 475 | threadContext->_transitEventBuffer.empty(); |
| 476 | } |
| 477 | |
| 478 | if (threadContext->HasBoundedQueueType()) { |
| 479 | return threadContext->GetSpscQueueUnion().BoundedSpscQueue.empty() && |
| 480 | threadContext->_transitEventBuffer.empty(); |
| 481 | } |
| 482 | } |
| 483 | |
| 484 | return false; |
| 485 | }; |
| 486 | |
| 487 | // First we iterate our existing cache and we look for any invalidated contexts |
| 488 | auto foundInvalidAndEmptyThreadContext = |
| 489 | std::find_if(_activeThreadContextsCache.begin(), _activeThreadContextsCache.end(), |
| 490 | findInvalidAndEmptyThreadContextCallback); |
| 491 | |
| 492 | while DEATH_UNLIKELY(foundInvalidAndEmptyThreadContext != std::end(_activeThreadContextsCache)) { |
| 493 | // If we found anything then remove it - Here if we have more than one to remove, we will try to acquire |
| 494 | // the lock multiple times, but it should be fine as it is unlikely to have that many to remove |
| 495 | threadManager.RemoveSharedInvalidatedThreadContext(*foundInvalidAndEmptyThreadContext); |
| 496 | |
| 497 | // We also need to remove it from _thread_context_cache, that is used only by the backend |
| 498 | _activeThreadContextsCache.erase(foundInvalidAndEmptyThreadContext); |
| 499 | |
| 500 | // And then look again |
| 501 | foundInvalidAndEmptyThreadContext = std::find_if(_activeThreadContextsCache.begin(), |
| 502 | _activeThreadContextsCache.end(), findInvalidAndEmptyThreadContextCallback); |
| 503 | } |
| 504 | } |
| 505 | |
| 506 | bool LoggerBackend::PopulateTransitEventFromThreadQueue(const std::uint8_t*& readPos, ThreadContext* threadContext, std::uint64_t tsNow) noexcept |
| 507 | { |
nothing calls this directly
no test coverage detected