Beispiel #1
0
void VertexArray::onSubjectStateChange(const gl::Context *context,
                                       angle::SubjectIndex index,
                                       angle::SubjectMessage message)
{
    switch (message)
    {
        case angle::SubjectMessage::ContentsChanged:
            setDependentDirtyBit(context, true, index);
            break;

        case angle::SubjectMessage::SubjectChanged:
            if (!IsElementArrayBufferSubjectIndex(index))
            {
                updateCachedBufferBindingSize(context, &mState.mVertexBindings[index]);
            }
            setDependentDirtyBit(context, false, index);
            break;

        case angle::SubjectMessage::BindingChanged:
            if (!IsElementArrayBufferSubjectIndex(index))
            {
                const Buffer *buffer = mState.mVertexBindings[index].getBuffer().get();
                updateCachedTransformFeedbackBindingValidation(index, buffer);
            }
            break;

        case angle::SubjectMessage::SubjectMapped:
            if (!IsElementArrayBufferSubjectIndex(index))
            {
                updateCachedMappedArrayBuffersBinding(mState.mVertexBindings[index]);
            }
            onStateChange(context, angle::SubjectMessage::SubjectMapped);
            break;

        case angle::SubjectMessage::SubjectUnmapped:
            setDependentDirtyBit(context, true, index);

            if (!IsElementArrayBufferSubjectIndex(index))
            {
                updateCachedMappedArrayBuffersBinding(mState.mVertexBindings[index]);
            }
            onStateChange(context, angle::SubjectMessage::SubjectUnmapped);
            break;

        default:
            UNREACHABLE();
            break;
    }
}
Beispiel #2
0
void VertexArray::setDependentDirtyBit(const gl::Context *context,
                                       bool contentsChanged,
                                       angle::SubjectIndex index)
{
    DirtyBitType dirtyBit = getDirtyBitFromIndex(contentsChanged, index);
    ASSERT(!mDirtyBitsGuard.valid() || mDirtyBitsGuard.value().test(dirtyBit));
    mDirtyBits.set(dirtyBit);
    onStateChange(context, angle::SubjectMessage::ContentsChanged);
}
Beispiel #3
0
SipPlugin::SipPlugin( const QString& pluginId, QObject* parent )
    : QObject( parent )
    , m_pluginId( pluginId )
{
    connect( this, SIGNAL( error( int, QString ) ), this, SLOT( onError( int,QString ) ) );
    connect( this, SIGNAL( stateChanged( SipPlugin::ConnectionState ) ), this, SLOT( onStateChange( SipPlugin::ConnectionState ) ) );
    connect( this, SIGNAL( peerOnline( QString ) ), this, SLOT( onPeerOnline( QString ) ) );
    connect( this, SIGNAL( peerOffline( QString ) ), this, SLOT( onPeerOffline( QString ) ) );
}
void MusicAudioRecorderCore::onRecordPlay()
{
    m_mpOutputFile->open(QIODevice::ReadOnly | QIODevice::Truncate);

    m_mpAudioOutputFile = new QAudioOutput(m_mFormatFile, this);
    connect(m_mpAudioOutputFile, SIGNAL(stateChanged(QAudio::State)), SLOT(onStateChange(QAudio::State)));
    m_mpAudioOutputFile->start(m_mpOutputFile);

}
Beispiel #5
0
void Session::setState(SessionState state)
{
    if(state == this->state)
        return;

    if(state == SessionState::Closed)
        peer = nullptr;

    assert(state == SessionState::Open && peer != nullptr && hasHash );

    this->state = state;
    onStateChange(state);
}
Beispiel #6
0
void BTN_Update(BTN * btn, BTN_STATE_ENUM state)
{
	if (btn)
	{
		BTN_STATE_ENUM new_state = debounce(btn, state);
		
		if (new_state != btn->current_state)
		{
			onStateChange(btn, new_state);
		}
		else
		{
			onSameState(btn);
		}
	}
}
Beispiel #7
0
void Button::sendStateMessage()
{
    Component::BailOutChecker checker (this);

    buttonStateChanged();

    if (checker.shouldBailOut())
        return;

    buttonListeners.callChecked (checker, [this] (Listener& l) { l.buttonStateChanged (this); });

    if (checker.shouldBailOut())
        return;

    if (onStateChange != nullptr)
        onStateChange();
}
lastfm::LNetworkConnectionMonitor::LNetworkConnectionMonitor( QObject* parent ) :
    NetworkConnectionMonitor( parent )
{
    m_nmInterface = new QDBusInterface( NM_DBUS_SERVICE,
                                        NM_DBUS_PATH,
                                        NM_DBUS_INTERFACE,
                                        QDBusConnection::systemBus(),
                                        this );
    if ( !m_nmInterface->isValid() )
    {
        qDebug() << "Unable to watch network state changes via D-Bus.";
        return;
    }

    //get current connection state
    QDBusReply<uint> reply = m_nmInterface->call( QDBus::AutoDetect, "state" );
    if ( reply.isValid() )
    {
        if ( reply.value() == NM_STATE_CONNECTED_GLOBAL )
        {
            setConnected( true );
        }
        else if ( reply.value() == NM_STATE_DISCONNECTED || reply.value() == NM_STATE_ASLEEP )
        {
            setConnected( false );
        }
    }
    else
    {
        qDebug() << "Error: " << reply.error();
    }

    //connect network manager signals
   m_nmInterface->connection().connect( NM_DBUS_SERVICE,
                                        NM_DBUS_PATH,
                                        NM_DBUS_INTERFACE,
                                        "StateChanged",
                                        this,
                                        SLOT( onStateChange( uint ) )
                                      );

}
Beispiel #9
0
BodyStreamBuffer::BodyStreamBuffer(ScriptState* scriptState,
                                   BytesConsumer* consumer)
    : UnderlyingSourceBase(scriptState),
      m_scriptState(scriptState),
      m_consumer(consumer),
      m_madeFromReadableStream(false) {
  v8::Local<v8::Value> bodyValue = toV8(this, scriptState);
  DCHECK(!bodyValue.IsEmpty());
  DCHECK(bodyValue->IsObject());
  v8::Local<v8::Object> body = bodyValue.As<v8::Object>();

  ScriptValue readableStream = ReadableStreamOperations::createReadableStream(
      scriptState, this,
      ReadableStreamOperations::createCountQueuingStrategy(scriptState, 0));
  DCHECK(!readableStream.isEmpty());
  V8HiddenValue::setHiddenValue(
      scriptState, body,
      V8HiddenValue::internalBodyStream(scriptState->isolate()),
      readableStream.v8Value());
  m_consumer->setClient(this);
  onStateChange();
}
LNetworkConnectionMonitor::LNetworkConnectionMonitor( QObject* parent ) :
    NetworkConnectionMonitor( parent )
{
    m_nmInterface = new QDBusInterface( QString( "org.freedesktop.NetworkManager" ),
                                        QString( "/org/freedesktop/NetworkManager" ),
                                        QString( "org.freedesktop.NetworkManager" ),
                                        QDBusConnection::systemBus(),
                                        this );

    //get current connection state
    QDBusInterface* dbusInterface = new QDBusInterface( QString( "org.freedesktop.NetworkManager" ),
                                                        QString( "/org/freedesktop/NetworkManager" ),
                                                        QString( "org.freedesktop.DBus.Properties" ),
                                                        QDBusConnection::systemBus(),
                                                        this );

    QDBusReply<QVariant> reply = dbusInterface->call( "Get", "org.freedesktop.NetworkManager", "state" );
    if ( reply.isValid() )
    {
        if ( reply.value() == Connected )
        {
            setConnected( true );
        }
        else if ( reply.value() == Disconnected )
        {
            setConnected( false );
        }
    }
    else
    {
        qDebug() << "Error: " << reply.error();
    }
    delete dbusInterface;

    //connect network manager signals
   connect( m_nmInterface, SIGNAL( StateChange( uint ) ), this, SLOT( onStateChange( uint ) ) );

}
Beispiel #11
0
void ToolInstance::onRun()
{
  QScrollBar* scrollbar = m_ui.edtOutput->verticalScrollBar();
  bool end = scrollbar->value() == scrollbar->maximum();
  int oldValue = scrollbar->value();

  m_ui.edtOutput->setTextColor(Qt::gray);
  m_ui.edtOutput->setPlainText(m_ui.edtOutput->toPlainText());

  if (end)
  {
    scrollbar->setValue(scrollbar->maximum());
  }
  else
  {
    scrollbar->setValue(oldValue);
  }

  QString exec = executable();
  if (exec.contains(" "))
  {
    exec = QString("\"%1\"").arg(exec);
  }
  exec.append(" ").append(arguments());

  m_process.start(exec, QIODevice::ReadOnly);
  if (m_process.waitForStarted(1000))
  {
    mCRL2log(mcrl2::log::info) << "Started " << exec.toStdString() << std::endl;
    m_ui.tabWidget->setCurrentIndex(1);
  }
  else
  {
    mCRL2log(mcrl2::log::error) << m_process.errorString().toStdString() << " (" << exec.toStdString() << ")" << std::endl;
    onStateChange(QProcess::NotRunning);
  }
}
Beispiel #12
0
void Widget::setState(MouseState inState)
{
    mMouseState = inState;
    onStateChange();
}
 void Link::turnOff(){
   if (isOn()) {
     Resource::turnOff();
     onStateChange(this);
   }
 }
Beispiel #14
0
ToolInstance::ToolInstance(QString filename, ToolInformation information, mcrl2::gui::qt::PersistentFileDialog* fileDialog, QWidget *parent) :
  QWidget(parent),
  m_filename(filename),
  m_info(information),
  m_fileDialog(fileDialog)
{
  m_ui.setupUi(this);

  connect(this, SIGNAL(colorChanged(QColor)), this, SLOT(onColorChanged(QColor)));

  connect(&m_process, SIGNAL(stateChanged(QProcess::ProcessState)), this, SLOT(onStateChange(QProcess::ProcessState)));
  connect(&m_process, SIGNAL(readyReadStandardOutput()), this, SLOT(onStandardOutput()));
  connect(&m_process, SIGNAL(readyReadStandardError()), this, SLOT(onStandardError()));
  connect(m_ui.btnRun, SIGNAL(clicked()), this, SLOT(onRun()));
  connect(m_ui.btnAbort, SIGNAL(clicked()), this, SLOT(onAbort()));
  connect(m_ui.btnSave, SIGNAL(clicked()), this, SLOT(onSave()));
  connect(m_ui.btnClear, SIGNAL(clicked()), m_ui.edtOutput, SLOT(clear()));

  QFileInfo fileInfo(filename);

  m_process.setWorkingDirectory(fileInfo.absoluteDir().absolutePath());
  m_ui.lblDirectoryValue->setText(fileInfo.absoluteDir().absolutePath());
  m_ui.lblFileValue->setText(fileInfo.fileName());

  if (m_info.hasOutput())
  {
    QDir dir = fileInfo.absoluteDir();
    QString newfile = fileInfo.baseName().append(".%1").arg(m_info.output);
    int filenr = 0;
    while(dir.exists(newfile))
    {
      filenr++;
      newfile = fileInfo.baseName().append("_%1.%2").arg(filenr).arg(m_info.output);
    }
    m_pckFileOut = new FilePicker(m_fileDialog, m_ui.pckFileOut);
    m_ui.pckFileOut->layout()->addWidget(m_pckFileOut);
    m_pckFileOut->setText(newfile);
  }
  else
  {
    m_pckFileOut = NULL;
    m_ui.lblFileOut->setVisible(false);
    m_ui.pckFileOut->setVisible(false);
  }

  if (m_info.hasSecondInput())
  {
    m_pckFileIn = new FilePicker(m_fileDialog, m_ui.pckFileIn, false);
    m_ui.pckFileIn->layout()->addWidget(m_pckFileIn);
  }
  else
  {
    m_pckFileIn = NULL;
    m_ui.lblFileIn->setVisible(false);
    m_ui.pckFileIn->setVisible(false);
  }

  QFormLayout *formLayout = new QFormLayout();
  formLayout->setFieldGrowthPolicy(QFormLayout::ExpandingFieldsGrow);
  for (int i = 0; i < m_info.options.count(); i++)
  {
    ToolOption option = m_info.options.at(i);
    QWidget *nameOpt = NULL;
    QCheckBox* cbOpt = NULL;
    QVBoxLayout *lytOpt = new QVBoxLayout();

    if (option.argument.type == EnumArgument)
    {
      nameOpt = new QLabel("<b>"+option.nameLong+": </b>");
    }
    else
    {
      cbOpt = new QCheckBox(option.nameLong + ": ", this);
      cbOpt->setChecked(option.standard);
      QFont font(cbOpt->font());
      font.setBold(true);
      cbOpt->setFont(font);
      nameOpt = cbOpt;
    }

    formLayout->addRow(nameOpt, lytOpt);

    QLabel *lblOpt = new QLabel(option.description, this);
    lblOpt->setAlignment(Qt::AlignJustify | Qt::AlignTop);
    lblOpt->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Minimum);
    lblOpt->setWordWrap(true);
    lytOpt->addWidget(lblOpt);

    if (!option.hasArgument())
    {
      m_optionValues.append(new OptionValue(option, cbOpt));
    }
    else
    {
      switch (option.argument.type)
      {
        case StringArgument:
        case LevelArgument:
        case IntegerArgument:
        case RealArgument:
        case BooleanArgument:
          {
            QHBoxLayout *lytArg = new QHBoxLayout();
            lytArg->setSpacing(6);

            QWidget *edtArg = NULL;

            switch (option.argument.type)
            {
              case LevelArgument:
                {
                  QLineEdit *edtLdt = new QLineEdit("verbose", this);
                  m_optionValues.append(new OptionValue(option, cbOpt, edtLdt));
                  edtArg = edtLdt;
                }
                break;
              case IntegerArgument:
                {
                  QSpinBox *edtSpb = new QSpinBox(this);
                  edtSpb->setRange(std::numeric_limits<int>::min(), std::numeric_limits<int>::max());
                  if (option.argument.optional)
                  {
                    QCheckBox *cbOptional = new QCheckBox(this);
                    lytArg->addWidget(cbOptional);
                    m_optionValues.append(new OptionValue(option, cbOpt, edtSpb, cbOptional));
                  }
                  else
                  {
                    m_optionValues.append(new OptionValue(option, cbOpt, edtSpb));
                  }
                  edtArg = edtSpb;
                }
                break;
              case RealArgument:
                {
                  QDoubleSpinBox *edtSpb = new QDoubleSpinBox(this);
                  edtSpb->setRange(std::numeric_limits<double>::min(), std::numeric_limits<double>::max());
                  if (option.argument.optional)
                  {
                    QCheckBox *cbOptional = new QCheckBox(this);
                    lytArg->addWidget(cbOptional);
                    m_optionValues.append(new OptionValue(option, cbOpt, edtSpb, cbOptional));
                  }
                  else
                  {
                    m_optionValues.append(new OptionValue(option, cbOpt, edtSpb));
                  }
                  edtArg = edtSpb;
                }
                break;
              case BooleanArgument:
                {
                  QCheckBox *edtChb = new QCheckBox("Yes", this);
                  m_optionValues.append(new OptionValue(option, cbOpt, edtChb));
                  edtArg = edtChb;
                }
                break;
              case StringArgument:
              default:
                {
                  QLineEdit *edtLdt = new QLineEdit(this);
                  m_optionValues.append(new OptionValue(option, cbOpt, edtLdt));
                  edtArg = edtLdt;
                }
                break;
            }
            edtArg->setMinimumWidth(300);

            lytArg->addWidget(edtArg);

            if (!option.argument.optional && option.argument.type != BooleanArgument)
            {
              QLabel *lblReq = new QLabel("*", this);
              lytArg->addWidget(lblReq);
            }

            QSpacerItem *spacer = new QSpacerItem(100, 20, QSizePolicy::Expanding);
            lytArg->addItem(spacer);
            lytOpt->addLayout(lytArg);
          }
          break;
        case FileArgument:
          {
            QHBoxLayout *lytArg = new QHBoxLayout();
            lytArg->setSpacing(6);

            FilePicker *edtArg = new FilePicker(m_fileDialog, this, false);
            lytArg->addWidget(edtArg);
            m_optionValues.append(new OptionValue(option, cbOpt, edtArg));

            if (!option.argument.optional)
            {
              QLabel *lblReq = new QLabel("*", this);
              lytArg->addWidget(lblReq);
            }

            QSpacerItem *spacer = new QSpacerItem(100, 20, QSizePolicy::Expanding);
            lytArg->addItem(spacer);
            lytOpt->addLayout(lytArg);
          }
          break;
        case EnumArgument:
          {
            QFormLayout *lytValues = new QFormLayout();
            lytValues->setSpacing(6);

            QButtonGroup *grpValues = new QButtonGroup(this);

            for (int j = 0; j < option.argument.values.count(); j++)
            {
              ToolValue val = option.argument.values.at(j);
              QRadioButton *rbVal = new QRadioButton(val.nameLong, this);
              rbVal->setChecked(val.standard);
              grpValues->addButton(rbVal);

              QLabel *lblVal = new QLabel(val.description, this);
              lblVal->setWordWrap(true);

              lytValues->addRow(rbVal, lblVal);
            }
            m_optionValues.append(new OptionValue(option, cbOpt, grpValues));

            lytOpt->addLayout(lytValues);
          }
          break;
        default:
          break;
      }
    }
  }
  m_ui.scrollWidget->setLayout(formLayout);
}
bool FastThread::threadLoop()
{
    for (;;) {

        // either nanosleep, sched_yield, or busy wait
        if (sleepNs >= 0) {
            if (sleepNs > 0) {
                ALOG_ASSERT(sleepNs < 1000000000);
                const struct timespec req = {0, sleepNs};
                nanosleep(&req, NULL);
            } else {
                sched_yield();
            }
        }
        // default to long sleep for next cycle
        sleepNs = FAST_DEFAULT_NS;

        // poll for state change
        const FastThreadState *next = poll();
        if (next == NULL) {
            // continue to use the default initial state until a real state is available
            // FIXME &initial not available, should save address earlier
            //ALOG_ASSERT(current == &initial && previous == &initial);
            next = current;
        }

        command = next->mCommand;
        if (next != current) {

            // As soon as possible of learning of a new dump area, start using it
            dumpState = next->mDumpState != NULL ? next->mDumpState : mDummyDumpState;
            logWriter = next->mNBLogWriter != NULL ? next->mNBLogWriter : &dummyLogWriter;
            setLog(logWriter);

            // We want to always have a valid reference to the previous (non-idle) state.
            // However, the state queue only guarantees access to current and previous states.
            // So when there is a transition from a non-idle state into an idle state, we make a
            // copy of the last known non-idle state so it is still available on return from idle.
            // The possible transitions are:
            //  non-idle -> non-idle    update previous from current in-place
            //  non-idle -> idle        update previous from copy of current
            //  idle     -> idle        don't update previous
            //  idle     -> non-idle    don't update previous
            if (!(current->mCommand & FastThreadState::IDLE)) {
                if (command & FastThreadState::IDLE) {
                    onIdle();
                    oldTsValid = false;
#ifdef FAST_MIXER_STATISTICS
                    oldLoadValid = false;
#endif
                    ignoreNextOverrun = true;
                }
                previous = current;
            }
            current = next;
        }
#if !LOG_NDEBUG
        next = NULL;    // not referenced again
#endif

        dumpState->mCommand = command;

        // << current, previous, command, dumpState >>

        switch (command) {
        case FastThreadState::INITIAL:
        case FastThreadState::HOT_IDLE:
            sleepNs = FAST_HOT_IDLE_NS;
            continue;
        case FastThreadState::COLD_IDLE:
            // only perform a cold idle command once
            // FIXME consider checking previous state and only perform if previous != COLD_IDLE
            if (current->mColdGen != coldGen) {
                int32_t *coldFutexAddr = current->mColdFutexAddr;
                ALOG_ASSERT(coldFutexAddr != NULL);
                int32_t old = android_atomic_dec(coldFutexAddr);
                if (old <= 0) {
                    syscall(__NR_futex, coldFutexAddr, FUTEX_WAIT_PRIVATE, old - 1, NULL);
                }
                int policy = sched_getscheduler(0);
                if (!(policy == SCHED_FIFO || policy == SCHED_RR)) {
                    ALOGE("did not receive expected priority boost");
                }
                // This may be overly conservative; there could be times that the normal mixer
                // requests such a brief cold idle that it doesn't require resetting this flag.
                isWarm = false;
                measuredWarmupTs.tv_sec = 0;
                measuredWarmupTs.tv_nsec = 0;
                warmupCycles = 0;
                sleepNs = -1;
                coldGen = current->mColdGen;
#ifdef FAST_MIXER_STATISTICS
                bounds = 0;
                full = false;
#endif
                oldTsValid = !clock_gettime(CLOCK_MONOTONIC, &oldTs);
                timestampStatus = INVALID_OPERATION;
            } else {
                sleepNs = FAST_HOT_IDLE_NS;
            }
            continue;
        case FastThreadState::EXIT:
            onExit();
            return false;
        default:
            LOG_ALWAYS_FATAL_IF(!isSubClassCommand(command));
            break;
        }

        // there is a non-idle state available to us; did the state change?
        if (current != previous) {
            onStateChange();
#if 1   // FIXME shouldn't need this
            // only process state change once
            previous = current;
#endif
        }

        // do work using current state here
        attemptedWrite = false;
        onWork();

        // To be exactly periodic, compute the next sleep time based on current time.
        // This code doesn't have long-term stability when the sink is non-blocking.
        // FIXME To avoid drift, use the local audio clock or watch the sink's fill status.
        struct timespec newTs;
        int rc = clock_gettime(CLOCK_MONOTONIC, &newTs);
        if (rc == 0) {
            //logWriter->logTimestamp(newTs);
            if (oldTsValid) {
                time_t sec = newTs.tv_sec - oldTs.tv_sec;
                long nsec = newTs.tv_nsec - oldTs.tv_nsec;
                ALOGE_IF(sec < 0 || (sec == 0 && nsec < 0),
                        "clock_gettime(CLOCK_MONOTONIC) failed: was %ld.%09ld but now %ld.%09ld",
                        oldTs.tv_sec, oldTs.tv_nsec, newTs.tv_sec, newTs.tv_nsec);
                if (nsec < 0) {
                    --sec;
                    nsec += 1000000000;
                }
                // To avoid an initial underrun on fast tracks after exiting standby,
                // do not start pulling data from tracks and mixing until warmup is complete.
                // Warmup is considered complete after the earlier of:
                //      MIN_WARMUP_CYCLES write() attempts and last one blocks for at least warmupNs
                //      MAX_WARMUP_CYCLES write() attempts.
                // This is overly conservative, but to get better accuracy requires a new HAL API.
                if (!isWarm && attemptedWrite) {
                    measuredWarmupTs.tv_sec += sec;
                    measuredWarmupTs.tv_nsec += nsec;
                    if (measuredWarmupTs.tv_nsec >= 1000000000) {
                        measuredWarmupTs.tv_sec++;
                        measuredWarmupTs.tv_nsec -= 1000000000;
                    }
                    ++warmupCycles;
                    if ((nsec > warmupNs && warmupCycles >= MIN_WARMUP_CYCLES) ||
                            (warmupCycles >= MAX_WARMUP_CYCLES)) {
                        isWarm = true;
                        dumpState->mMeasuredWarmupTs = measuredWarmupTs;
                        dumpState->mWarmupCycles = warmupCycles;
                    }
                }
                sleepNs = -1;
                if (isWarm) {
                    if (sec > 0 || nsec > underrunNs) {
                        ATRACE_NAME("underrun");
                        // FIXME only log occasionally
                        ALOGV("underrun: time since last cycle %d.%03ld sec",
                                (int) sec, nsec / 1000000L);
                        dumpState->mUnderruns++;
                        ignoreNextOverrun = true;
                    } else if (nsec < overrunNs) {
                        if (ignoreNextOverrun) {
                            ignoreNextOverrun = false;
                        } else {
                            // FIXME only log occasionally
                            ALOGV("overrun: time since last cycle %d.%03ld sec",
                                    (int) sec, nsec / 1000000L);
                            dumpState->mOverruns++;
                        }
                        // This forces a minimum cycle time. It:
                        //  - compensates for an audio HAL with jitter due to sample rate conversion
                        //  - works with a variable buffer depth audio HAL that never pulls at a
                        //    rate < than overrunNs per buffer.
                        //  - recovers from overrun immediately after underrun
                        // It doesn't work with a non-blocking audio HAL.
                        sleepNs = forceNs - nsec;
                    } else {
                        ignoreNextOverrun = false;
                    }
                }
#ifdef FAST_MIXER_STATISTICS
                if (isWarm) {
                    // advance the FIFO queue bounds
                    size_t i = bounds & (dumpState->mSamplingN - 1);
                    bounds = (bounds & 0xFFFF0000) | ((bounds + 1) & 0xFFFF);
                    if (full) {
                        bounds += 0x10000;
                    } else if (!(bounds & (dumpState->mSamplingN - 1))) {
                        full = true;
                    }
                    // compute the delta value of clock_gettime(CLOCK_MONOTONIC)
                    uint32_t monotonicNs = nsec;
                    if (sec > 0 && sec < 4) {
                        monotonicNs += sec * 1000000000;
                    }
                    // compute raw CPU load = delta value of clock_gettime(CLOCK_THREAD_CPUTIME_ID)
                    uint32_t loadNs = 0;
                    struct timespec newLoad;
                    rc = clock_gettime(CLOCK_THREAD_CPUTIME_ID, &newLoad);
                    if (rc == 0) {
                        if (oldLoadValid) {
                            sec = newLoad.tv_sec - oldLoad.tv_sec;
                            nsec = newLoad.tv_nsec - oldLoad.tv_nsec;
                            if (nsec < 0) {
                                --sec;
                                nsec += 1000000000;
                            }
                            loadNs = nsec;
                            if (sec > 0 && sec < 4) {
                                loadNs += sec * 1000000000;
                            }
                        } else {
                            // first time through the loop
                            oldLoadValid = true;
                        }
                        oldLoad = newLoad;
                    }
#ifdef CPU_FREQUENCY_STATISTICS
                    // get the absolute value of CPU clock frequency in kHz
                    int cpuNum = sched_getcpu();
                    uint32_t kHz = tcu.getCpukHz(cpuNum);
                    kHz = (kHz << 4) | (cpuNum & 0xF);
#endif
                    // save values in FIFO queues for dumpsys
                    // these stores #1, #2, #3 are not atomic with respect to each other,
                    // or with respect to store #4 below
                    dumpState->mMonotonicNs[i] = monotonicNs;
                    dumpState->mLoadNs[i] = loadNs;
#ifdef CPU_FREQUENCY_STATISTICS
                    dumpState->mCpukHz[i] = kHz;
#endif
                    // this store #4 is not atomic with respect to stores #1, #2, #3 above, but
                    // the newest open & oldest closed halves are atomic with respect to each other
                    dumpState->mBounds = bounds;
                    ATRACE_INT("cycle_ms", monotonicNs / 1000000);
                    ATRACE_INT("load_us", loadNs / 1000);
                }
#endif
            } else {
                // first time through the loop
                oldTsValid = true;
                sleepNs = periodNs;
                ignoreNextOverrun = true;
            }
            oldTs = newTs;
        } else {
            // monotonic clock is broken
            oldTsValid = false;
            sleepNs = periodNs;
        }

    }   // for (;;)

    // never return 'true'; Thread::_threadLoop() locks mutex which can result in priority inversion
}