mirror of
				https://github.com/OpenMW/openmw.git
				synced 2025-11-04 05:56:39 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			89 lines
		
	
	
	
		
			2.5 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			89 lines
		
	
	
	
		
			2.5 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
#include "readerscache.hpp"
 | 
						|
 | 
						|
#include <stdexcept>
 | 
						|
 | 
						|
namespace ESM
 | 
						|
{
 | 
						|
    ReadersCache::BusyItem::BusyItem(ReadersCache& owner, std::list<Item>::iterator item) noexcept
 | 
						|
        : mOwner(owner)
 | 
						|
        , mItem(item)
 | 
						|
    {
 | 
						|
    }
 | 
						|
 | 
						|
    ReadersCache::BusyItem::~BusyItem() noexcept
 | 
						|
    {
 | 
						|
        mOwner.releaseItem(mItem);
 | 
						|
    }
 | 
						|
 | 
						|
    ReadersCache::ReadersCache(std::size_t capacity)
 | 
						|
        : mCapacity(capacity)
 | 
						|
    {
 | 
						|
    }
 | 
						|
 | 
						|
    ReadersCache::BusyItem ReadersCache::get(std::size_t index)
 | 
						|
    {
 | 
						|
        const auto indexIt = mIndex.find(index);
 | 
						|
        std::list<Item>::iterator it;
 | 
						|
        if (indexIt == mIndex.end())
 | 
						|
        {
 | 
						|
            closeExtraReaders();
 | 
						|
            it = mBusyItems.emplace(mBusyItems.end());
 | 
						|
            mIndex.emplace(index, it);
 | 
						|
        }
 | 
						|
        else
 | 
						|
        {
 | 
						|
            switch (indexIt->second->mState)
 | 
						|
            {
 | 
						|
                case State::Busy:
 | 
						|
                    throw std::logic_error("ESMReader at index " + std::to_string(index) + " is busy");
 | 
						|
                case State::Free:
 | 
						|
                    it = indexIt->second;
 | 
						|
                    mBusyItems.splice(mBusyItems.end(), mFreeItems, it);
 | 
						|
                    break;
 | 
						|
                case State::Closed:
 | 
						|
                    closeExtraReaders();
 | 
						|
                    it = indexIt->second;
 | 
						|
                    if (it->mName.has_value())
 | 
						|
                    {
 | 
						|
                        it->mReader.open(*it->mName);
 | 
						|
                        it->mName.reset();
 | 
						|
                    }
 | 
						|
                    mBusyItems.splice(mBusyItems.end(), mClosedItems, it);
 | 
						|
                    break;
 | 
						|
            }
 | 
						|
            it->mState = State::Busy;
 | 
						|
        }
 | 
						|
 | 
						|
        return BusyItem(*this, it);
 | 
						|
    }
 | 
						|
 | 
						|
    void ReadersCache::closeExtraReaders()
 | 
						|
    {
 | 
						|
        while (!mFreeItems.empty() && mBusyItems.size() + mFreeItems.size() + 1 > mCapacity)
 | 
						|
        {
 | 
						|
            const auto it = mFreeItems.begin();
 | 
						|
            if (it->mReader.isOpen())
 | 
						|
            {
 | 
						|
                it->mName = it->mReader.getName();
 | 
						|
                it->mReader.close();
 | 
						|
            }
 | 
						|
            mClosedItems.splice(mClosedItems.end(), mFreeItems, it);
 | 
						|
            it->mState = State::Closed;
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    void ReadersCache::releaseItem(std::list<Item>::iterator it) noexcept
 | 
						|
    {
 | 
						|
        assert(it->mState == State::Busy);
 | 
						|
        if (it->mReader.isOpen())
 | 
						|
        {
 | 
						|
            mFreeItems.splice(mFreeItems.end(), mBusyItems, it);
 | 
						|
            it->mState = State::Free;
 | 
						|
        }
 | 
						|
        else
 | 
						|
        {
 | 
						|
            mClosedItems.splice(mClosedItems.end(), mBusyItems, it);
 | 
						|
            it->mState = State::Closed;
 | 
						|
        }
 | 
						|
    }
 | 
						|
}
 |