pBlock GarbageCollector:: runOnce(unsigned frame_counter) { size_t free_memory = availableMemoryForSingleAllocation(); BlockCache::cache_t cacheCopy = cache_->clone(); size_t allocatedMemory = BlockCacheInfo::cacheByteSize (cacheCopy); if (allocatedMemory < free_memory*MAX_FRACTION_FOR_CACHES) return pBlock(); // No need to release memory pBlock releasedBlock = getOldestBlock(frame_counter, cacheCopy, 2); if (!releasedBlock) return pBlock(); // Nothing to release Heightmap::Block::pGlBlock glblock = releasedBlock->glblock; size_t blockMemory = glblock ? glblock->allocated_bytes_per_element() * releasedBlock->block_layout().texels_per_block () : 0; if (true) TaskInfo(format("Removing block %s last used %u frames ago. Freeing %s, total free %s, cache %s, %u blocks") % releasedBlock->getRegion () % (frame_counter - releasedBlock->frame_number_last_used) % DataStorageVoid::getMemorySizeText( blockMemory ) % DataStorageVoid::getMemorySizeText( free_memory ) % DataStorageVoid::getMemorySizeText( allocatedMemory ) % cacheCopy.size() ); return releasedBlock; }
void BlockCache:: test() { // It should store allocated blocks readily available { Reference r1; Reference r2 = r1.right (); BlockLayout bl(2,2,1); VisualizationParams::ptr vp; pBlock b1(new Block(r1, bl, vp)); pBlock b2(new Block(r2, bl, vp)); BlockCache c; c.insert (b1); c.insert (b2); pBlock b3 = c.find(r1); pBlock b4 = c.find(r2); pBlock b5 = c.find (r2.parentHorizontal ()); pBlock b6 = c.find (r1.left ()); EXCEPTION_ASSERT( b1 == b3 ); EXCEPTION_ASSERT( b2 == b4 ); EXCEPTION_ASSERT( r2 == r1.right () ); EXCEPTION_ASSERT_EQUALS( r2.parentHorizontal (), r1 ); EXCEPTION_ASSERT( b1 == b5 ); EXCEPTION_ASSERT( b6 == pBlock() ); } }
pBlock getOldestBlock(unsigned frame_counter, BlockCache::cache_t& cache, unsigned min_age) { typedef const BlockCache::cache_t::value_type pair; auto i = std::max_element(cache.begin(), cache.end(), [frame_counter](pair& a, pair& b) { unsigned age_a = frame_counter - a.second->frame_number_last_used; unsigned age_b = frame_counter - b.second->frame_number_last_used; return age_a < age_b; }); if (i == cache.end()) return pBlock(); unsigned age = frame_counter - i->second->frame_number_last_used; if (age < min_age) return pBlock(); return i->second; }
pBlock BlockCache:: find( const Reference& ref ) const { lock_guard<mutex> l(mutex_); cache_t::const_iterator itr = cache_.find( ref ); if (itr != cache_.end()) { return itr->second; } else { return pBlock(); } }
TInt CIniData::GetSetting(const TDesC &aValue, TPtrC &aSetting) /** Retrieves the value for a particular setting within a block @param aValue The setting to be retrieved @param aSetting On return it contains the value for the setting @return KErrNone if successful or KErrArgument for fields simply left blank. If the global BlockState is unknown returns KErrNotReady. */ { TInt valid(KErrNotReady); if (BlockState != E_UNKNOWN) { // first check for CONDITION field // if we are NOT looking for this field, we need to trim off any condition // field from the block because there may be a setting within it we // want to ignore during our search for this field TPtrC pBlock(block); TInt tempEnd = blockEnd; TPtrC Condition = CONDITION; if (aValue.Compare(Condition) != 0) { TPtr varCondToken = iToken->Des(); _LIT(varCondTokenString, "%S="); varCondToken.Format(varCondTokenString, &Condition); TInt CondPos = pBlock.FindF(varCondToken); if (CondPos != KErrNotFound) { tempEnd = CondPos; } } // now look for the actual value TBool searchAgain = EFalse; _LIT(varTokenString, "%S="); TPtr varToken = iToken->Des(); varToken.Format(varTokenString, &aValue); TInt pos = KErrNotFound; do { searchAgain = EFalse; pos = pBlock.FindF(varToken); if (pos != KErrNotFound && pos < tempEnd) { // check that this is a complete match, not a substring // match against another similar field, e.g. LoginScript // must only match against "LoginScript" not "UseLoginScript" if (pos > 0) { // Previous character must be white space const TChar previousCharacter = pBlock[pos - 1]; if (previousCharacter.IsSpace()) { // make sure we haven't overrun our block TInt length = varToken.Length(); if (pos + length < tempEnd) { TLex lex(pBlock.Mid(pos + length)); // if enclosed by quotes, extract the text within if (lex.Peek() == '"') { lex.SkipAndMark(1); // start of data // stop at end of quote or line while(lex.Peek() != '"' && lex.Peek() != 10 && lex.Peek() != 13) { lex.Inc(); } } else if(lex.Peek() == 10 || lex.Peek() == 13) // skip empty or blank field value { return KErrArgument; } else // skip any unwanted spaces or tabs in a field value { TBool fieldValFound=EFalse; while(lex.Peek() != 10 && lex.Peek() != 13) { if(!fieldValFound) { while(lex.Peek() == 9 || lex.Peek() == 32) // skip any space or a tab { lex.SkipAndMark(1); } if(lex.Peek() == 10 || lex.Peek() == 13) // field value simply filled with space or tab { return KErrArgument; } } fieldValFound=ETrue; // start of real data lex.Inc(); } } aSetting.Set(lex.MarkedToken().Ptr(),lex.MarkedToken().Length()); valid = KErrNone; } } else { // E.g. LoginScript matched against UseLoginScript -> must look // for another match after the current one pBlock.Set(pBlock.Mid(pos+1)); searchAgain = ETrue; } } } } while(searchAgain); } return valid; }