/* This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #pragma once enum class resource_state { none, loading, good, failed }; using resource_timestamp = std::chrono::steady_clock::time_point; // takes containers providing access to specific element through operator[] // with elements of std::pair // the element should provide method release() freeing resources owned by the element template class garbage_collector { public: // constructor: garbage_collector( Container_ &Container, unsigned int const Secondstolive, std::size_t const Sweepsize, std::string const Resourcename = "resource" ) : m_unusedresourcetimetolive{ std::chrono::seconds{ Secondstolive } }, m_unusedresourcesweepsize{ Sweepsize }, m_resourcename{ Resourcename }, m_container{ Container } {} // methods: // performs resource sweep. returns: number of released resources int sweep() { m_resourcetimestamp = std::chrono::steady_clock::now(); // garbage collection sweep is limited to a number of records per call, to reduce impact on framerate auto const sweeplastindex = std::min( m_resourcesweepindex + m_unusedresourcesweepsize, m_container.size() ); auto const blanktimestamp { std::chrono::steady_clock::time_point() }; int releasecount{ 0 }; for( auto resourceindex = m_resourcesweepindex; resourceindex < sweeplastindex; ++resourceindex ) { if( ( m_container[ resourceindex ].second != blanktimestamp ) && ( m_resourcetimestamp - m_container[ resourceindex ].second > m_unusedresourcetimetolive ) ) { m_container[ resourceindex ].first->release(); m_container[ resourceindex ].second = blanktimestamp; ++releasecount; } } /* if( releasecount ) { WriteLog( "Resource garbage sweep released " + std::to_string( releasecount ) + " " + ( releasecount == 1 ? m_resourcename : m_resourcename + "s" ) ); } */ m_resourcesweepindex = ( m_resourcesweepindex + m_unusedresourcesweepsize >= m_container.size() ? 0 : // if the next sweep chunk is beyond actual data, so start anew m_resourcesweepindex + m_unusedresourcesweepsize ); return releasecount; } std::chrono::steady_clock::time_point timestamp() const { return m_resourcetimestamp; } private: // members: std::chrono::nanoseconds const m_unusedresourcetimetolive; typename Container_::size_type const m_unusedresourcesweepsize; std::string const m_resourcename; Container_ &m_container; typename Container_::size_type m_resourcesweepindex { 0 }; std::chrono::steady_clock::time_point m_resourcetimestamp { std::chrono::steady_clock::now() }; };