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; }
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(); } } }
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; }