/** \file
 *
 *  Contains the RingBufferVoid class implementation.
 *
 *  Copyright (c) 2007,2008,2009 MBARI
 *  MBARI Proprietary Information.  All Rights Reserved
 */

#include "RingBuffer.h"

RingBufferVoid::RingBufferVoid( const bool freeOnCleanup )
    : start_( NULL ),
      end_( NULL ),
      freeOnCleanup_( freeOnCleanup )
{}

RingBufferVoid::~RingBufferVoid()
{
    freeAll();
    while( NULL != end_ )
    {
        start_ = end_->getNext();
        delete start_;
        if( start_ == end_ )
        {
            start_ = NULL;
            end_ = NULL;
        }
    }
}

bool RingBufferVoid::isEmpty()
{
    return NULL == start_;
}

void RingBufferVoid::freeAll()
{
    while( freeOnCleanup_ && !isEmpty() )
    {
        void* item( pop() );
        if( NULL != item )
        {
            free( item );
        }
    }
}

void RingBufferVoid::push( void* item )
{
    MutexLocker lock( mutex_ );
    if( NULL == end_ || end_->getNext() == start_ )
    {
        // Empty or Full Buffer
        end_ = new ListEntry<void*>( item, end_, NULL == end_ ? NULL : end_->getNext(), true );
    }
    else
    {
        // Buffer with space
        end_ = end_->getNext();
        end_->setItem( item );
    }
    if( NULL == start_ )
    {
        start_ = end_;
    }
}

void* RingBufferVoid::pop()
{
    MutexLocker lock( mutex_ );
    void* returnValue( 0 );
    if( !isEmpty() )
    {
        returnValue = start_->getItem();
        if( start_ == end_ )
        {
            start_ = NULL;
        }
        else
        {
            start_ = start_->getNext();
        }
    }
    return returnValue;
}

void* RingBufferVoid::peek()
{
    MutexLocker lock( mutex_ );
    void* returnValue( 0 );
    if( !isEmpty() )
    {
        returnValue = start_->getItem();
    }
    return returnValue;
}
