72 size_t current_used{mUsedMemory.load(std::memory_order_relaxed)};
74 new_used = current_used + bytes;
75 if (new_used > mMaxMemory.load(std::memory_order_relaxed)) {
76 mCountThrow.fetch_add(1, std::memory_order_relaxed);
78 mMaxMemory.load(std::memory_order_relaxed));
80 }
while (!mUsedMemory.compare_exchange_weak(current_used, new_used,
81 std::memory_order_acq_rel,
82 std::memory_order_relaxed));
86 p = mUpstream->allocate(bytes, alignment);
88 mUsedMemory.fetch_sub(bytes, std::memory_order_relaxed);
89#ifdef BOUNDED_MR_STATS
90 mStats.upstreamFailures.fetch_add(1, std::memory_order_relaxed);
95#ifdef BOUNDED_MR_STATS
96 size_t peak = mStats.peak.load(std::memory_order_relaxed);
97 while (new_used > peak &&
98 !mStats.peak.compare_exchange_weak(peak, new_used,
99 std::memory_order_relaxed)) {
101 mStats.live.fetch_add(1, std::memory_order_relaxed);
102 mStats.nAlloc.fetch_add(1, std::memory_order_relaxed);
103 mStats.totalAlloc.fetch_add(bytes, std::memory_order_relaxed);
105 size_t ma = mStats.maxAlign.load(std::memory_order_relaxed);
106 while (alignment > ma && !mStats.maxAlign.compare_exchange_weak(ma, alignment, std::memory_order_relaxed)) {
114 mUpstream->deallocate(p, bytes, alignment);
115 mUsedMemory.fetch_sub(bytes, std::memory_order_relaxed);
116#ifdef BOUNDED_MR_STATS
117 mStats.live.fetch_sub(1, std::memory_order_relaxed);
118 mStats.nFree.fetch_add(1, std::memory_order_relaxed);
119 mStats.totalFreed.fetch_add(bytes, std::memory_order_relaxed);
143 size_t current = mMaxMemory.load(std::memory_order_relaxed);
144 if (
max == current) {
148 size_t used = mUsedMemory.load(std::memory_order_acquire);
150 mCountThrow.fetch_add(1, std::memory_order_relaxed);
153 if (mMaxMemory.compare_exchange_weak(current,
max,
154 std::memory_order_release,
155 std::memory_order_relaxed)) {
158 if (current ==
max) {
167 const auto throw_ = mCountThrow.load(std::memory_order_relaxed);
168 const auto used =
static_cast<double>(mUsedMemory.load(std::memory_order_relaxed));
169 const auto maxm = mMaxMemory.load(std::memory_order_relaxed);
171 if (maxm == std::numeric_limits<size_t>::max()) {
172 ret += std::format(
"maxthrow={} maxmem=unbounded used={:.2f} GB", throw_, used /
constants::GB);
174 ret += std::format(
"maxthrow={} maxmem={:.2f} GB used={:.2f} GB ({:.2f}%)", throw_, (
double)maxm /
constants::GB, used /
constants::GB, 100.0 * used / (
double)maxm);
176#ifdef BOUNDED_MR_STATS
177 ret += std::format(
" peak={:.2f} GB live={} nAlloc={} nFree={} totalAlloc={:.2f} GB totalFreed={:.2f} GB maxAlign={} upstreamFail={}",
178 (
float)mStats.peak.load(std::memory_order_relaxed) /
constants::GB,
179 mStats.live.load(std::memory_order_relaxed),
180 mStats.nAlloc.load(std::memory_order_relaxed),
181 mStats.nFree.load(std::memory_order_relaxed),
182 (
float)mStats.totalAlloc.load(std::memory_order_relaxed) /
constants::GB,
183 (
float)mStats.totalFreed.load(std::memory_order_relaxed) /
constants::GB,
184 mStats.maxAlign.load(std::memory_order_relaxed),
185 mStats.upstreamFailures.load(std::memory_order_relaxed));