<commit_before>/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 <NAME>
 *
 * This library is open source and may be redistributed and/or modified under
 * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
 * (at your option) any later version.  The full license is in LICENSE file
 * included with this distribution, and on the openscenegraph.org website.
 *
 * 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
 * OpenSceneGraph Public License for more details.
*/

#include <osgDB/ObjectCache>
#include <osgDB/Options>

using namespace osgDB;

bool ObjectCache::ClassComp::operator() (const ObjectCache::FileNameOptionsPair& lhs, const ObjectCache::FileNameOptionsPair& rhs) const
{
    return lhs.first < rhs.first || *lhs.second < *rhs.second;
}

////////////////////////////////////////////////////////////////////////////////////////////
//
// ObjectCache
//
ObjectCache::ObjectCache():
    osg::Referenced(true)
{
//    OSG_NOTICE<<"Constructed ObjectCache"<<std::endl;
}

ObjectCache::~ObjectCache()
{
//    OSG_NOTICE<<"Destructed ObjectCache"<<std::endl;
}

void ObjectCache::addObjectCache(ObjectCache* objectCache)
{
    // don't allow a cache to be added to itself.
    if (objectCache==this) return;

    // lock both ObjectCache to prevent their contents from being modified by other threads while we merge.
    OpenThreads::ScopedLock<OpenThreads::Mutex> lock1(_objectCacheMutex);
    OpenThreads::ScopedLock<OpenThreads::Mutex> lock2(objectCache->_objectCacheMutex);

    OSG_DEBUG<<"Inserting objects to main ObjectCache "<<objectCache->_objectCache.size()<<std::endl;

    _objectCache.insert(objectCache->_objectCache.begin(), objectCache->_objectCache.end());
}


void ObjectCache::addEntryToObjectCache(const std::string& filename, osg::Object* object, double timestamp, const Options *options)
{
    OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_objectCacheMutex);
    _objectCache[FileNameOptionsPair(filename, osg::clone(options))] = ObjectTimeStampPair(object,timestamp);
    OSG_DEBUG<<"Adding "<<filename<<" with options '"<<(options ? options->getOptionString() : "")<<"' to ObjectCache "<<this<<std::endl;
}

osg::Object* ObjectCache::getFromObjectCache(const std::string& fileName, const Options *options)
{
    OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_objectCacheMutex);
    ObjectCacheMap::iterator itr = _objectCache.find(FileNameOptionsPair(fileName, options));
    if (itr!=_objectCache.end())
    {
        osg::ref_ptr<const osgDB::Options> o = itr->first.second;
        if (o.valid())
        {
            OSG_DEBUG<<"Found "<<fileName<<" with options '"<< o->getOptionString()<< "' in ObjectCache "<<this<<std::endl;
        }
        else
        {
            OSG_DEBUG<<"Found "<<fileName<<" in ObjectCache "<<this<<std::endl;
        }
        return itr->second.first.get();
    }
    else return 0;
}

osg::ref_ptr<osg::Object> ObjectCache::getRefFromObjectCache(const std::string& fileName, const Options *options)
{
    OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_objectCacheMutex);
    ObjectCacheMap::iterator itr;
    itr = _objectCache.find(FileNameOptionsPair(fileName, options));
    if (itr!=_objectCache.end())
    {
        osg::ref_ptr<const osgDB::Options> o = itr->first.second;
        if (o.valid())
        {
            OSG_DEBUG<<"Found "<<fileName<<" with options '"<< o->getOptionString()<< "' in ObjectCache "<<this<<std::endl;
        }
        else
        {
            OSG_DEBUG<<"Found "<<fileName<<" in ObjectCache "<<this<<std::endl;
        }
        return itr->second.first.get();
    }
    else return 0;
}

void ObjectCache::updateTimeStampOfObjectsInCacheWithExternalReferences(double referenceTime)
{
    OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_objectCacheMutex);

    // look for objects with external references and update their time stamp.
    for(ObjectCacheMap::iterator itr=_objectCache.begin();
        itr!=_objectCache.end();
        ++itr)
    {
        // if ref count is greater the 1 the object has an external reference.
        if (itr->second.first->referenceCount()>1)
        {
            // so update it time stamp.
            itr->second.second = referenceTime;
        }
    }
}

void ObjectCache::removeExpiredObjectsInCache(double expiryTime)
{
    OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_objectCacheMutex);

    // Remove expired entries from object cache
    ObjectCacheMap::iterator oitr = _objectCache.begin();
    while(oitr != _objectCache.end())
    {
        if (oitr->second.second<=expiryTime)
        {
            _objectCache.erase(oitr++);
        }
        else
        {
            ++oitr;
        }
    }
}

void ObjectCache::removeFromObjectCache(const std::string& fileName, const Options *options)
{
    OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_objectCacheMutex);
    ObjectCacheMap::iterator itr = _objectCache.find(FileNameOptionsPair(fileName, options));
    if (itr!=_objectCache.end()) _objectCache.erase(itr);
}

void ObjectCache::clear()
{
    OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_objectCacheMutex);
    _objectCache.clear();
}

void ObjectCache::releaseGLObjects(osg::State* state)
{
    OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_objectCacheMutex);

    for(ObjectCacheMap::iterator itr = _objectCache.begin();
        itr != _objectCache.end();
        ++itr)
    {
        osg::Object* object = itr->second.first.get();
        object->releaseGLObjects(state);
    }
}
<commit_msg>Added handling of the possibility of null Options pointers<commit_after>/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 <NAME>
 *
 * This library is open source and may be redistributed and/or modified under
 * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
 * (at your option) any later version.  The full license is in LICENSE file
 * included with this distribution, and on the openscenegraph.org website.
 *
 * 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
 * OpenSceneGraph Public License for more details.
*/

#include <osgDB/ObjectCache>
#include <osgDB/Options>

using namespace osgDB;

bool ObjectCache::ClassComp::operator() (const ObjectCache::FileNameOptionsPair& lhs, const ObjectCache::FileNameOptionsPair& rhs) const
{
    // check if filename are the same
    if (lhs.first < rhs.first) return true;
    if (rhs.first < lhs.first) return false;

    // check if Options pointers are the same.
    if (lhs.second == rhs.second) return false;

    // need to compare Options pointers
    if (lhs.second.valid() && rhs.second.valid())
    {
        // lhs & rhs have valid Options objects
        return *lhs.second < *rhs.second;
    }

    // finally use pointer comparison, expecting at least one will be NULL pointer
    return lhs.second < rhs.second;
}

////////////////////////////////////////////////////////////////////////////////////////////
//
// ObjectCache
//
ObjectCache::ObjectCache():
    osg::Referenced(true)
{
//    OSG_NOTICE<<"Constructed ObjectCache"<<std::endl;
}

ObjectCache::~ObjectCache()
{
//    OSG_NOTICE<<"Destructed ObjectCache"<<std::endl;
}

void ObjectCache::addObjectCache(ObjectCache* objectCache)
{
    // don't allow a cache to be added to itself.
    if (objectCache==this) return;

    // lock both ObjectCache to prevent their contents from being modified by other threads while we merge.
    OpenThreads::ScopedLock<OpenThreads::Mutex> lock1(_objectCacheMutex);
    OpenThreads::ScopedLock<OpenThreads::Mutex> lock2(objectCache->_objectCacheMutex);

    OSG_DEBUG<<"Inserting objects to main ObjectCache "<<objectCache->_objectCache.size()<<std::endl;

    _objectCache.insert(objectCache->_objectCache.begin(), objectCache->_objectCache.end());
}


void ObjectCache::addEntryToObjectCache(const std::string& filename, osg::Object* object, double timestamp, const Options *options)
{
    OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_objectCacheMutex);
    _objectCache[FileNameOptionsPair(filename, osg::clone(options))] = ObjectTimeStampPair(object,timestamp);
    OSG_DEBUG<<"Adding "<<filename<<" with options '"<<(options ? options->getOptionString() : "")<<"' to ObjectCache "<<this<<std::endl;
}

osg::Object* ObjectCache::getFromObjectCache(const std::string& fileName, const Options *options)
{
    OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_objectCacheMutex);
    ObjectCacheMap::iterator itr = _objectCache.find(FileNameOptionsPair(fileName, options));
    if (itr!=_objectCache.end())
    {
        osg::ref_ptr<const osgDB::Options> o = itr->first.second;
        if (o.valid())
        {
            OSG_DEBUG<<"Found "<<fileName<<" with options '"<< o->getOptionString()<< "' in ObjectCache "<<this<<std::endl;
        }
        else
        {
            OSG_DEBUG<<"Found "<<fileName<<" in ObjectCache "<<this<<std::endl;
        }
        return itr->second.first.get();
    }
    else return 0;
}

osg::ref_ptr<osg::Object> ObjectCache::getRefFromObjectCache(const std::string& fileName, const Options *options)
{
    OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_objectCacheMutex);
    ObjectCacheMap::iterator itr;
    itr = _objectCache.find(FileNameOptionsPair(fileName, options));
    if (itr!=_objectCache.end())
    {
        osg::ref_ptr<const osgDB::Options> o = itr->first.second;
        if (o.valid())
        {
            OSG_DEBUG<<"Found "<<fileName<<" with options '"<< o->getOptionString()<< "' in ObjectCache "<<this<<std::endl;
        }
        else
        {
            OSG_DEBUG<<"Found "<<fileName<<" in ObjectCache "<<this<<std::endl;
        }
        return itr->second.first.get();
    }
    else return 0;
}

void ObjectCache::updateTimeStampOfObjectsInCacheWithExternalReferences(double referenceTime)
{
    OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_objectCacheMutex);

    // look for objects with external references and update their time stamp.
    for(ObjectCacheMap::iterator itr=_objectCache.begin();
        itr!=_objectCache.end();
        ++itr)
    {
        // if ref count is greater the 1 the object has an external reference.
        if (itr->second.first->referenceCount()>1)
        {
            // so update it time stamp.
            itr->second.second = referenceTime;
        }
    }
}

void ObjectCache::removeExpiredObjectsInCache(double expiryTime)
{
    OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_objectCacheMutex);

    // Remove expired entries from object cache
    ObjectCacheMap::iterator oitr = _objectCache.begin();
    while(oitr != _objectCache.end())
    {
        if (oitr->second.second<=expiryTime)
        {
            _objectCache.erase(oitr++);
        }
        else
        {
            ++oitr;
        }
    }
}

void ObjectCache::removeFromObjectCache(const std::string& fileName, const Options *options)
{
    OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_objectCacheMutex);
    ObjectCacheMap::iterator itr = _objectCache.find(FileNameOptionsPair(fileName, options));
    if (itr!=_objectCache.end()) _objectCache.erase(itr);
}

void ObjectCache::clear()
{
    OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_objectCacheMutex);
    _objectCache.clear();
}

void ObjectCache::releaseGLObjects(osg::State* state)
{
    OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_objectCacheMutex);

    for(ObjectCacheMap::iterator itr = _objectCache.begin();
        itr != _objectCache.end();
        ++itr)
    {
        osg::Object* object = itr->second.first.get();
        object->releaseGLObjects(state);
    }
}

{'fraction_non_alphanumeric': 0.14335191755364082, 'fraction_numerical': 0.0027031593174522725, 'mean_word_length': 3.5622350674373795, 'pattern_counts': {'":': 0, '<': 195, '<?xml version=': 0, '>': 71, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4119360', 'n_tokens_mistral': 3481, 'n_tokens_neox': 3509, 'n_words': 795}