bool PipelineProducer::__process( unsigned int serial )
{
    QMutexLocker lock( &m_pleMutex );

    // set the serial number for this processing run
    setProcessingSerial( serial );

    for( OutputPinMap::iterator itr = m_outputPins.begin();
         itr != m_outputPins.end(); ++itr )
    {
        IOutputPin* out = itr->second.getPtr();
        out->pre();
    }

    // do the actual producing
    lock.unlock();
    bool retval = this->produce();
    lock.relock();

    for( OutputPinMap::iterator itr = m_outputPins.begin();
         itr != m_outputPins.end(); ++itr )
    {
        IOutputPin* out = itr->second.getPtr();
        out->post();
    }

    lock.unlock();
    if(!retval) setState(PLE_ERROR);

    return retval;
}
int PipelineElement::maxOutputQueueSize() const
{
    QMutexLocker lock( &m_pleMutex );

    int maxQueueSize = 0;

    for( PipelineElement::OutputPinMap::const_iterator itr = m_outputPins.begin();
        itr!=m_outputPins.end(); ++itr )
    {
        IOutputPin* outputPin = itr->second;
        int queueSize = outputPin->maxDataOnConnection();
        if( queueSize > maxQueueSize )
            maxQueueSize = queueSize;
    }
    return maxQueueSize;
}
bool PipelineProcessor::__process( unsigned int serial )
{
    assert( requiredPinsConnected() );
    assert( getState() == RUNNING );

    QMutexLocker lock( &m_pleMutex );

    // set the serial number
    m_serial = serial;

    bool nullDetected = false;

    // call pre on input pins and look for null data items
    for( InputPinMap::iterator itr = m_inputPins.begin();
         itr != m_inputPins.end(); ++itr )
    {
        IInputPin* in = itr->second.getPtr();

        // only check synchronous connections
        if( in->isConnected() && in->isSynchronous() )
        {
            unsigned int serial;
            bool isNull;
            in->peekNext(serial, isNull);
            if( isNull ) nullDetected = true;
        }
        in->pre();
    }

    // if one data item is a null
    // we throw away all data from all synchronous pins
    if( nullDetected )
    {
        for( InputPinMap::iterator itr = m_inputPins.begin();
             itr != m_inputPins.end(); ++itr )
        {
            IInputPin* in = itr->second.getPtr();

            if( in->isConnected() && in->isSynchronous() )
            {
                // just remove first data item in the
                in->removeFirst();
            }
        }
        return true;
    }

    // call pre on output pins
    for( OutputPinMap::iterator itr = m_outputPins.begin();
         itr != m_outputPins.end(); ++itr )
    {
        IOutputPin* out = itr->second.getPtr();
        out->pre();
    }

    // do the actual processing
    lock.unlock();

    // we do not want properties to change in the middle of an operation
    QMutexLocker lock2( m_propertyMutex );
    bool retval = this->process();
    lock2.unlock();
    lock.relock();

    // call post on input pins
    for( InputPinMap::iterator itr = m_inputPins.begin();
         itr != m_inputPins.end(); ++itr )
    {
        IInputPin* in = itr->second.getPtr();
        in->post();
    }

    // call post on output pins
    for( OutputPinMap::iterator itr = m_outputPins.begin();
         itr != m_outputPins.end(); ++itr )
    {
        IOutputPin* out = itr->second.getPtr();
        out->post();
    }
    lock.unlock();

    if(!retval && getState() != ERROR)
    {
        QString msg = tr("Method process() on PipelineProcessor %1 returned false "
                         "but error state was not set.").arg(this->getName());
        qWarning() << msg;
    }

    return retval;
}
void PipelineProcessor::__process()
{
    assert( requiredPinsConnected() );
    assert( dataAvailableOnInputPins() );

    QMutexLocker lock( &m_pleMutex );

    // we do not want properties to change in the middle of an operation
    QMutexLocker lock2( m_propertyMutex );

    std::vector<unsigned int> serials;
    serials.reserve( m_inputPins.size() );
    bool nullDetected = false;
    for( InputPinMap::iterator itr = m_inputPins.begin();
         itr != m_inputPins.end() && !nullDetected; ++itr )
    {
        IInputPin* in = itr->second.getPtr();
        in->pre();
        if( in->isConnected() &&
            in->isSynchronous() )
        {
            unsigned int serial = in->getNextSerial();
            serials.push_back( serial );
            if( serial == 0 )
            {
                nullDetected = true;
            }

        }
    }

    // if one data item is a null
    // we throw away all data from all synchronous pins
    if( nullDetected )
    {
        for( InputPinMap::iterator itr = m_inputPins.begin();
             itr != m_inputPins.end(); ++itr )
        {
            IInputPin* in = itr->second.getPtr();

            // just remove first data in queue
            RefPtr<Data> d;
            in->getUntyped(d);
        }

        // call post on input pins
        for( InputPinMap::iterator itr = m_inputPins.begin();
             itr != m_inputPins.end(); ++itr )
        {
            IInputPin* in = itr->second.getPtr();
            in->post();
        }
    }
    else
    {
        // sort on serial number
        std::sort( serials.begin(), serials.end(), std::greater<unsigned int>() );

        // check for equality
        // we are a processor, so there is guaranteed to be at least one input pin
        unsigned int max = serials[0];
        bool fastforward = false;
        for( std::vector<unsigned int>::iterator itr = serials.begin();
             itr != serials.end(); ++itr )
        {
            if( (*itr) < max)
            {
                fastforward = true;

                // TODO, will this ever occur in current model?
                assert( false );
            }

        }

//        bool fastforwardSucceeded = true;
//        if(fastforward)
//        {
//            qDebug() << "Fastforward needed on pin inputs of processor " << getName();

//            for( InputPinMap::iterator itr = m_inputPins.begin();
//                 itr != m_inputPins.end(); ++itr )
//            {
//                IInputPin* in = itr->second.getPtr();
//                if( in->isConnected() && in->isSynchronous() )
//                {
//                    fastforwardSucceeded = in->fastforward( max ) && fastforwardSucceeded;
//                }
//            }
//        }

        // call pre on output pins
        for( OutputPinMap::iterator itr = m_outputPins.begin();
             itr != m_outputPins.end(); ++itr )
        {
            IOutputPin* out = itr->second.getPtr();
            out->pre();
        }

        // call process function which does the actual work
        // set the serial number for this processing run
        this->setProcessingSerial( max );

        // do the actual processing
        this->process();

        // call post on input pins
        for( InputPinMap::iterator itr = m_inputPins.begin();
             itr != m_inputPins.end(); ++itr )
        {
            IInputPin* in = itr->second.getPtr();
            in->post();
        }

        // call post on output pins
        for( OutputPinMap::iterator itr = m_outputPins.begin();
             itr != m_outputPins.end(); ++itr )
        {
            IOutputPin* out = itr->second.getPtr();
            out->post();
        }
    }
}