Program Listing for File FrameMemory.cpp

Return to documentation for file (lib/DataStructures/FrameMemory.cpp)

#include "DataStructures/FrameMemory.h"
#include "DataStructures/Frame.h"

namespace lsd_slam
{

FrameMemory::FrameMemory()
{
}

FrameMemory& FrameMemory::getInstance()
{
    static FrameMemory theOneAndOnly;
    return theOneAndOnly;
}

void FrameMemory::releaseBuffers()
{
    boost::unique_lock<boost::mutex> lock(accessMutex);
    int total = 0;


    for(auto p : availableBuffers)
    {
        LOGF_IF(DEBUG, Conf().print.memoryDebugInfo, "deleting %d buffers of size %d!", (int)p.second.size(), (int)p.first);

        total += p.second.size() * p.first;

        for(unsigned int i=0;i<p.second.size();i++)
        {
            delete (char*)p.second[i];
            bufferSizes.erase(p.second[i]);
        }

        p.second.clear();
    }
    availableBuffers.clear();

    LOGF_IF(DEBUG, Conf().print.memoryDebugInfo, "released %.1f MB!", total / (1000000.0f));
}


void* FrameMemory::getBuffer(unsigned int sizeInByte)
{
    boost::unique_lock<boost::mutex> lock(accessMutex);

    if (availableBuffers.count(sizeInByte) > 0)
    {
        std::vector< void* >& availableOfSize = availableBuffers.at(sizeInByte);
        if (availableOfSize.empty())
        {
            void* buffer = allocateBuffer(sizeInByte);
//          assert(buffer != 0);
            return buffer;
        }
        else
        {
            void* buffer = availableOfSize.back();
            availableOfSize.pop_back();

//          assert(buffer != 0);
            return buffer;
        }
    }
    else
    {
        void* buffer = allocateBuffer(sizeInByte);
//      assert(buffer != 0);
        return buffer;
    }
}

float* FrameMemory::getFloatBuffer(unsigned int size)
{
    return (float*)getBuffer(sizeof(float) * size);
}

void FrameMemory::returnBuffer(void* buffer)
{
    if(buffer==0) return;

    boost::unique_lock<boost::mutex> lock(accessMutex);

    unsigned int size = bufferSizes.at(buffer);
    //printf("returnFloatBuffer(%d)\n", size);
    if (availableBuffers.count(size) > 0)
        availableBuffers.at(size).push_back(buffer);
    else
    {
        std::vector< void* > availableOfSize;
        availableOfSize.push_back(buffer);
        availableBuffers.insert(std::make_pair(size, availableOfSize));
    }
}

void* FrameMemory::allocateBuffer(unsigned int size)
{
    void* buffer = (void*)(new char[size]);
    LOG_IF(DEBUG, Conf().print.memoryDebugInfo) << "Alloc " << size << " at " << std::ios::hex << buffer;
    bufferSizes.insert(std::make_pair(buffer, size));
    return buffer;
}

boost::shared_lock<boost::shared_mutex> FrameMemory::activateFrame(Frame* frame)
{
    boost::unique_lock<boost::mutex> lock(activeFramesMutex);
    if(frame->isActive)
        activeFrames.remove(frame);
    activeFrames.push_front(frame);
    frame->isActive = true;
    return boost::shared_lock<boost::shared_mutex>(frame->activeMutex);
}

void FrameMemory::deactivateFrame(Frame* frame)
{
    boost::unique_lock<boost::mutex> lock(activeFramesMutex);
    if(!frame->isActive) return;
    activeFrames.remove(frame);

    while(!frame->minimizeInMemory())
        LOG(WARNING) << "cannot deactivateFrame frame " << frame->id()
                                << ", as some active locks are lingering. May cause deadlock!"; // do it in a loop, to make sure it is really, really deactivated.

    frame->isActive = false;
}

void FrameMemory::pruneActiveFrames()
{
    boost::unique_lock<boost::mutex> lock(activeFramesMutex);

    while((int)activeFrames.size() > maxLoopClosureCandidates + 20)
    {
        if(!activeFrames.back()->minimizeInMemory())
        {
            if(!activeFrames.back()->minimizeInMemory())
            {
                LOG(WARNING) << "failed to minimize frame " << activeFrames.back()->id() << " twice. maybe some active-lock is lingering?";
                return;  // pre-emptive return if could not deactivate.
            }
        }
        activeFrames.back()->isActive = false;
        activeFrames.pop_back();
    }
}

}