fix: fall back to non-pmr BoundedPriorityQueue on runtimes without std::pmr#1086
Open
Leppard wants to merge 1 commit into
Open
fix: fall back to non-pmr BoundedPriorityQueue on runtimes without std::pmr#1086Leppard wants to merge 1 commit into
Leppard wants to merge 1 commit into
Conversation
…d::pmr BoundedPriorityQueue uses std::pmr (multiset + monotonic_buffer_resource + unsynchronized_pool_resource). On Apple platforms those runtime symbols ship in the system libc++ only from iOS 17.0 / macOS 14.0 / tvOS 17.0 / watchOS 10.0 (_LIBCPP_AVAILABILITY_HAS_PMR). Because libc++ currently leaves the pmr availability markup empty (llvm/llvm-project#40340), using std::pmr below those versions compiles cleanly but aborts at dyld load time: Symbol not found: std::__1::pmr::memory_resource::~memory_resource() so every app crashes at launch on iOS < 17 (reported in software-mansion#1071). Gate the std::pmr implementation behind AUDIOAPI_HAS_PMR (auto-detected from _LIBCPP_AVAILABILITY_HAS_PMR, overridable). When pmr is unavailable, back the same std::multiset with an in-object, non-pmr pool allocator that preserves the original design intent: a fixed buffer, node recycling via an intrusive free list, and no heap allocation. The container and its public API are unchanged, so iOS 17+/Android keep the std::pmr fast path untouched. Adds BoundedPriorityQueueTest (forces the fallback path) covering ordering, capacity bounds, node recycling under 100k insert/erase cycles, heterogeneous lowerBound/upperBound, and extract/mutate/reinsert. Fixes software-mansion#1071 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
BoundedPriorityQueueis backed bystd::pmr(multiset+monotonic_buffer_resource+unsynchronized_pool_resource). On Apple platforms those runtime symbols only exist in the systemlibc++from iOS 17.0 / macOS 14.0 / tvOS 17.0 / watchOS 10.0 (_LIBCPP_AVAILABILITY_HAS_PMR→_LIBCPP_INTRODUCED_IN_LLVM_16).libc++ currently leaves the pmr availability markup empty (see the
// TODO: Enable std::pmr markup once llvm/llvm-project#40340 ...note in<__configuration/availability.h>), so usingstd::pmrbelow those versions compiles without any diagnostic but aborts at dyld load time:That crashes every app at launch on iOS < 17 — see #1071 (also confirmed there on production App Store builds and real devices).
Approach
Following @mdydek's preference in #1071 (keep
std::pmr, add an STL fallback for older runtimes):std::pmrimplementation behind a newAUDIOAPI_HAS_PMRmacro, auto-detected from libc++'s own_LIBCPP_AVAILABILITY_HAS_PMRso it tracks each platform's threshold automatically (Android keeps pmr). It can be overridden by definingAUDIOAPI_HAS_PMRbefore including the header.std::multisetwith an in-object, non-pmr pool allocator (FixedBlockPool+PoolAllocator) that preserves the original design intent: a fixed buffer, node recycling via an intrusive free list, and no heap allocation — so the audio-thread / real-time behavior is kept on the fallback too, not regressed to a heap-backedstd::multiset.The container type and the entire public API are unchanged, so iOS 17+ / Android keep the existing
std::pmrfast path untouched — only sub‑iOS‑17 (and equivalent) builds compile the fallback.Tests
Adds
common/cpp/test/src/utils/BoundedPriorityQueueTest.cpp. It#definesAUDIOAPI_HAS_PMR 0so the fallback path is exercised even on CI hosts whose libc++ has pmr (the default path is already compiled into the rest of the suite). Covers:popreturns the smallest element first,lowerBound/upperBound(transparent comparator),extract→ mutate key → reinsert with hint, and rangeerase.Verified locally: builds clean for
arm64-apple-ios15.1with zeropmrsymbols in the resulting object (nm), the default (pmr) branch still compiles on a pmr-capable host, and all 4 gtest cases pass. (ASan/UBSan/TSan variants left to CI — the local macOS 26 ASan runtime hangs at startup even for a trivial program.)Notes
ios_min_version = '14.0'claim becomes correct again with the fallback in place.Fixes #1071