bool PipelineElement::visit( QList< PipelineElement* >& ordering,
                             QSet< PipelineElement* >& visited )
{
    // check if this node is already in partial ordering
    if( ordering.contains( this ))
        return true;

    // check for cycles
    if( visited.contains( this ))
    {
        // cycle detected
        ordering.append( this );
        return false;
    }
    visited.insert( this );

    // visit all incoming connections
    for( PipelineElement::InputPinMap::const_iterator itr = m_inputPins.begin();
        itr!=m_inputPins.end(); ++itr )
    {
        IInputPin* inputPin = itr->second;
        if( inputPin->isConnected() )
        {
            PipelineElement* node = inputPin->getConnection()->fromPin()->getOwner();
            // directly quit if cycle detected
            if( !node->visit( ordering, visited ) )
                return false;
        }
    }
    // go up in call stack
    visited.remove( this );
    ordering.append( this );
    return true;
}
Пример #2
0
int PipelineElement::maxInputQueueSize() const
{
    QMutexLocker lock( &m_pleMutex );

    int maxQueueSize = 0;

    for( PipelineElement::InputPinMap::const_iterator itr = m_inputPins.begin();
        itr!=m_inputPins.end(); ++itr )
    {
        int queueSize = 0;

        IInputPin* inputPin = itr->second;
        if( inputPin->isConnected() )
        {
            queueSize = inputPin->getConnection()->size();
        }

        if( queueSize > maxQueueSize ) maxQueueSize = queueSize;
    }
    return maxQueueSize;
}
Пример #3
0
bool PipelineElement::dataAvailableOnInputPins() const
{
    QMutexLocker lock( &m_pleMutex );

    for( InputPinMap::const_iterator itr = m_inputPins.begin();
         itr != m_inputPins.end();
         ++itr )
    {
        IInputPin* in = itr->second.getPtr();

        // only automatically check synchronous connections
        if( in->isConnected() &&
            in->isSynchronous() )
        {
            // check for data
            if( !in->hasData() )
            {
                return false;
            }
        }
    }
    return true;
}
bool PipelineElement::__init()
{
    assert( getState() == PLUNDEFINED );

    QMutexLocker lock( &m_pleMutex );
    m_hasAsynchronousPin = false;
    m_hasSynchronousPin = false;
    for( InputPinMap::const_iterator itr = m_inputPins.begin();
         itr != m_inputPins.end();
         ++itr )
    {
        IInputPin* in = itr->second.getPtr();

        // only automatically check synchronous connections
        if( in->isConnected() )
        {
            if( in->isSynchronous() )
            {
                m_hasSynchronousPin = true;
            }
            else
            {
                m_hasAsynchronousPin = true;
            }
        }
    }
    lock.unlock();

    if( !this->init() )
    {
        setState(PLERROR);
        return false;
    }
    setState(PLINITIALIZED);
    return true;
}
Пример #5
0
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;
}
Пример #6
0
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();
        }
    }
}
bool PipelineElement::dataAvailableOnInputPins( unsigned int& nextSerial )
{
    // synchronous processor
    if( m_hasSynchronousPin )
    {
        std::vector<unsigned int> serials;
        for( InputPinMap::const_iterator itr = m_inputPins.begin();
             itr != m_inputPins.end();
             ++itr )
        {
            IInputPin* in = itr->second.getPtr();

            // only check synchronous connections
            if( in->isConnected() )
            {
                if( in->isSynchronous() )
                {
                    if( in->hasData() )
                    {
                        unsigned int serial;
                        bool isNull;
                        in->peekNext(serial, isNull);
                        serials.push_back( serial );
                    }
                    else
                    {
                        return false;
                    }
                }
            }
        }

        // check if all serials are the same (which should be the case)
        bool valid = true;
        for( unsigned int i=0; i<serials.size() && valid; ++i)
        {
            valid = (serials[0] == serials[i]);
        }

        // the model should guarantee that
        // this should never happen obviously
        if( !valid )
        {
            setError( PlvPipelineRuntimeError, "Input corrupted" );
            return false;
        }

        // save the serial
        nextSerial = serials[0];

        return true;
    }
    // asynchronous processor, only has asynchronous pins
    else if( m_hasAsynchronousPin )
    {
        std::vector<unsigned int> serials;
        for( InputPinMap::const_iterator itr = m_inputPins.begin();
             itr != m_inputPins.end();
             ++itr )
        {
            IInputPin* in = itr->second.getPtr();

            // only check asynchronous connections
            if( in->isConnected() ) //&& in->isAsynchronous() )
            {
                if( in->hasData() )
                {
                    unsigned int serial;
                    bool isNull;
                    in->peekNext(serial, isNull);
                    serials.push_back(serial);
                }
            }
        }

        if( serials.size() > 0 )
        {
            std::sort( serials.begin(), serials.end() );
            // return smallest serial
            nextSerial = serials[0];
            return true;
        }
    }
    return false;
}