You've already forked libopenshot
mirror of
https://github.com/OpenShot/libopenshot.git
synced 2026-06-08 22:17:28 -07:00
82 lines
1.9 KiB
C++
82 lines
1.9 KiB
C++
/**
|
|
* @file
|
|
* @brief Cross-platform helper to encourage returning freed memory to the OS
|
|
*
|
|
* @ref License
|
|
*/
|
|
|
|
// Copyright (c) 2008-2025 OpenShot Studios, LLC
|
|
//
|
|
// SPDX-License-Identifier: LGPL-3.0-or-later
|
|
|
|
#include "MemoryTrim.h"
|
|
|
|
#include <atomic>
|
|
#include <chrono>
|
|
#include <cstdint>
|
|
|
|
#if defined(__GLIBC__)
|
|
#include <malloc.h>
|
|
#elif defined(_WIN32)
|
|
#include <malloc.h>
|
|
#elif defined(__APPLE__)
|
|
#include <malloc/malloc.h>
|
|
#endif
|
|
|
|
namespace {
|
|
// Limit trim attempts to once per interval to avoid spamming platform calls
|
|
constexpr uint64_t kMinTrimIntervalMs = 30000; // 30s debounce
|
|
std::atomic<uint64_t> g_last_trim_ms{0};
|
|
std::atomic<bool> g_trim_in_progress{false};
|
|
|
|
uint64_t NowMs() {
|
|
using namespace std::chrono;
|
|
return duration_cast<milliseconds>(steady_clock::now().time_since_epoch()).count();
|
|
}
|
|
} // namespace
|
|
|
|
namespace openshot {
|
|
|
|
bool TrimMemoryToOS() noexcept {
|
|
const uint64_t now_ms = NowMs();
|
|
const uint64_t last_ms = g_last_trim_ms.load(std::memory_order_relaxed);
|
|
|
|
// Skip if we recently trimmed
|
|
if (now_ms - last_ms < kMinTrimIntervalMs)
|
|
return false;
|
|
|
|
// Only one trim attempt runs at a time
|
|
bool expected = false;
|
|
if (!g_trim_in_progress.compare_exchange_strong(expected, true, std::memory_order_acq_rel))
|
|
return false;
|
|
|
|
bool did_trim = false;
|
|
|
|
#if defined(__GLIBC__)
|
|
// GLIBC exposes malloc_trim to release free arenas back to the OS
|
|
malloc_trim(0);
|
|
did_trim = true;
|
|
#elif defined(_WIN32)
|
|
// MinGW/MSYS2 expose _heapmin to compact the CRT heap
|
|
_heapmin();
|
|
did_trim = true;
|
|
#elif defined(__APPLE__)
|
|
// macOS uses the malloc zone API to relieve memory pressure
|
|
malloc_zone_t* zone = malloc_default_zone();
|
|
malloc_zone_pressure_relief(zone, 0);
|
|
did_trim = true;
|
|
#else
|
|
// Platforms without a known trimming API
|
|
did_trim = false;
|
|
#endif
|
|
|
|
if (did_trim) {
|
|
g_last_trim_ms.store(now_ms, std::memory_order_relaxed);
|
|
}
|
|
|
|
g_trim_in_progress.store(false, std::memory_order_release);
|
|
return did_trim;
|
|
}
|
|
|
|
} // namespace openshot
|