📄 aflibmemcache.cc
字号:
/* * Copyright: (C) 2001 Bruce W. Forsberg * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Bruce Forsberg forsberg@tns.net * */#ifdef HAVE_CONFIG_H#include <config.h>#endif#include "aflibMemCache.h"#include "aflibMemNode.h"#include "aflib.h"#include "aflibData.h"#define CACHE_SIZE_MAX 1 * 1024 * 1024 // Max cache size totallong long aflibMemCache::_cache_size_total = 0;/*! \brief Constructor.*/aflibMemCache::aflibMemCache(){ _cache_counter = 0; _cache_size_local = 0; _enable = FALSE; if (getenv("AFLIB_CACHE_SIZE")) _cache_size_max = atoi(getenv("AFLIB_CACHE_SIZE")); else _cache_size_max = CACHE_SIZE_MAX;}/*! \brief Destructor.*/aflibMemCache::~aflibMemCache(){ clearCache();}/*! \brief Returns the current state of caching for this object. Return the state of the cache. TRUE means caching is enabled.*/boolaflibMemCache::getCacheEnable(){ return(_enable);}/*! \brief Set the state of caching for this object.*/voidaflibMemCache::setCacheEnable(bool enable){ _enable = enable;}/*! \brief Returns the maximum allowed size of the cache.*/long longaflibMemCache::getCacheMax() const{ return (_cache_size_max);}/*! \brief Gets the current size of the cache for this object only.*/ long longaflibMemCache::getCacheLocal() const{ return (_cache_size_local);}/*! \brief Gets the total size of all caches added together.*/long longaflibMemCache::getCacheTotal() const{ return (_cache_size_total);}voidaflibMemCache::cacheData( long long position, aflibData& data){ // This function will receive a block of data to be cached. This function will store the // data into the cache so that it can be read later. It will first of all check the // cache size. If the cache limit has been exceeded then old data will be discarded. // IF we have exceeded the max cache size then reduce the cache size if (_cache_size_local > _cache_size_max) { reduceCache(); } // Check if the data can replace an existing nodes data if (!checkExistingNode(position, data)) { // Create new node and insert into array createNewNode(0, data.getLength(), position, data); }} voidaflibMemCache::lookupData( long long& position, int& num_samples){ // This function will determine if there is data available in the cache that can be // used. It will modify the position and num_samples passed in to indicate the data // that is still needed that is not in the cache. If all the needed data is in the // cache then this function will return num_samples equal to 0. if(position == -1) return; map< long long, aflibMemNode* >::iterator it; map< long long, aflibMemNode* >::iterator it_prev; bool processed = FALSE; // loop thru all memory nodes for (it = _node_array.begin(); it != _node_array.end(); it++) { // Loop until we find tbe memory node past the start of this memory location if ((*it).first > position) { processed = TRUE; // If no node before this position then no data in cache for this position if (it == _node_array.begin()) { break; } // IF data is not in node then done if (position > (*it_prev).first + (long long)(*it_prev).second->getSize()) { break; } // Use the previous node to modify data calcPosition(position, num_samples, it_prev); break; } it_prev = it; } // Check the last node if none others were found if ((_node_array.size() != 0) && processed == FALSE) { calcPosition(position, num_samples, it_prev); }}voidaflibMemCache::calcPosition( long long& position, int& num_samples, map< long long, aflibMemNode* >::iterator it){ // Using the memory node passed in modify the position and num_samples based on // how much data can be retrieved from this node int diff; // Find the amount of data that might be available diff = (int) ( (*it).first + (*it).second->getSize() - position ); // IF there is data that we can use if (diff > 0) { // IF all data is available if (diff >= num_samples) { position += num_samples; num_samples = 0; } else { position += diff; num_samples -= diff; } }}voidaflibMemCache::reduceCache(){ // One or more nodes should be removed to keep memory usage in check. // Currently this uses a very simple algorithm. It deletes the nodes with // the smallest positions. This needs to change in the future. long long size; map< long long, aflibMemNode* >::iterator it; // Delete cache nodes until local cache is less than max while (_cache_size_local > _cache_size_max) { it = _node_array.begin(); // reduce total cache size of node size = ((*it).second->getSize() * (*it).second->getChannels() * 4); _cache_size_local -= size; _cache_size_total -= size; // Remove node delete (*it).second; _node_array.erase(it); }}boolaflibMemCache::checkExistingNode( long long position, aflibData& data){ // This will check if the data can replace an existing node. If it does then TRUE // will be returned. There are three possible cases that are covered in this function. // They are cased on the following diagram. // // |---New Data---| // // Case 1 |----------| // Case 2 |---------------------| // Case 3 |----> // // Case 1 is the existing node starts before the new data node and ends before the // new data node ends. // Case 2 is the existing node starts before the new data node and ends after the // new data node ends. // Case 3 is the existing node starts after the new data node and ends either before // or after the new node ends. // // node_position and node_size are the position and sizes of the current node that we // are iterating on. size and position is the size and position of the new data that // is to be added. size and position can change as we add data to an existing node. // orig_position and orig size is the original size and position of the new data and // does not change. map< long long, aflibMemNode* >::iterator it; bool processed = FALSE; long long node_position; long long node_size; long long size; long long orig_position; long long orig_size; int i, j; int chans; chans = data.getConfig().getChannels(); size = data.getLength(); orig_position = position; orig_size = size; // Loop thru all nodes for (it = _node_array.begin(); it != _node_array.end(); it++) { node_position = (*it).first; node_size = (*it).second->getSize(); // IF end point of node is beyond new data start then if (node_position + node_size > position) { // IF beginning point of node is before or equal new data start if (node_position <= position) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -