content/media/webrtc/LoadManager.cpp
author Randell Jesup <rjesup@jesup.org>
Sun, 08 Jun 2014 18:37:14 -0400
changeset 207821 b5067fbd502ee7ff5d7e6b0a54edcd6d0fcd847f
parent 197835 0b1fdffd07e5422d58f5ce34243a5ab20783efa5
child 208085 6c40063b2088a9acaa3694d6821555770279e00f
child 209514 dc93584a0948d18d4e8a69a14a14fc915fc720d5
permissions -rw-r--r--
Bug 1022376: Properly shut down LoadMonitor threads r=jib

/* -*- Mode: C++; tab-width: 50; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#include "LoadManager.h"
#include "LoadMonitor.h"
#include "nsString.h"
#include "prlog.h"
#include "prtime.h"
#include "prinrval.h"
#include "prsystem.h"

#include "nsString.h"
#include "nsThreadUtils.h"
#include "nsReadableUtils.h"
#include "nsNetUtil.h"

// NSPR_LOG_MODULES=LoadManager:5
PRLogModuleInfo *gLoadManagerLog = nullptr;
#undef LOG
#undef LOG_ENABLED
#if defined(PR_LOGGING)
#define LOG(args) PR_LOG(gLoadManagerLog, PR_LOG_DEBUG, args)
#define LOG_ENABLED() PR_LOG_TEST(gLoadManagerLog, 5)
#else
#define LOG(args)
#define LOG_ENABLED() (false)
#endif

namespace mozilla {

LoadManager::LoadManager(int aLoadMeasurementInterval,
                         int aAveragingMeasurements,
                         float aHighLoadThreshold,
                         float aLowLoadThreshold)
  : mLoadSum(0.0f),
    mLoadSumMeasurements(0),
    mOveruseActive(false),
    mLoadMeasurementInterval(aLoadMeasurementInterval),
    mAveragingMeasurements(aAveragingMeasurements),
    mHighLoadThreshold(aHighLoadThreshold),
    mLowLoadThreshold(aLowLoadThreshold),
    mCurrentState(webrtc::kLoadNormal)
{
#if defined(PR_LOGGING)
  if (!gLoadManagerLog)
    gLoadManagerLog = PR_NewLogModule("LoadManager");
#endif
  LOG(("LoadManager - Initializing (%dms x %d, %f, %f)",
       mLoadMeasurementInterval, mAveragingMeasurements,
       mHighLoadThreshold, mLowLoadThreshold));
  MOZ_ASSERT(mHighLoadThreshold > mLowLoadThreshold);
  mLoadMonitor = new LoadMonitor(mLoadMeasurementInterval);
  mLoadMonitor->Init(mLoadMonitor);
  mLoadMonitor->SetLoadChangeCallback(this);
}

LoadManager::~LoadManager()
{
  LOG(("LoadManager: shutting down LoadMonitor"));
  mLoadMonitor->Shutdown();
}

void
LoadManager::LoadChanged(float aSystemLoad, float aProcesLoad)
{
  // Update total load, and total amount of measured seconds.
  mLoadSum += aSystemLoad;
  mLoadSumMeasurements++;

  if (mLoadSumMeasurements >= mAveragingMeasurements) {
    double averagedLoad = mLoadSum / (float)mLoadSumMeasurements;

    webrtc::CPULoadState oldState = mCurrentState;

    if (mOveruseActive || averagedLoad > mHighLoadThreshold) {
      LOG(("LoadManager - LoadStressed"));
      mCurrentState = webrtc::kLoadStressed;
    } else if (averagedLoad < mLowLoadThreshold) {
      LOG(("LoadManager - LoadRelaxed"));
      mCurrentState = webrtc::kLoadRelaxed;
    } else {
      LOG(("LoadManager - LoadNormal"));
      mCurrentState = webrtc::kLoadNormal;
    }

    if (oldState != mCurrentState)
      LoadHasChanged();

    mLoadSum = 0;
    mLoadSumMeasurements = 0;
  }
}

void
LoadManager::OveruseDetected()
{
  LOG(("LoadManager - Overuse Detected"));
  mOveruseActive = true;
  if (mCurrentState != webrtc::kLoadStressed) {
    mCurrentState = webrtc::kLoadStressed;
    LoadHasChanged();
  }
}

void
LoadManager::NormalUsage()
{
  LOG(("LoadManager - Overuse finished"));
  mOveruseActive = false;
}

void
LoadManager::LoadHasChanged()
{
  LOG(("LoadManager - Signaling LoadHasChanged to %d listeners", mObservers.Length()));
  for (size_t i = 0; i < mObservers.Length(); i++) {
    mObservers.ElementAt(i)->onLoadStateChanged(mCurrentState);
  }
}

void
LoadManager::AddObserver(webrtc::CPULoadStateObserver * aObserver)
{
  LOG(("LoadManager - Adding Observer"));
  mObservers.AppendElement(aObserver);
}

void
LoadManager::RemoveObserver(webrtc::CPULoadStateObserver * aObserver)
{
  LOG(("LoadManager - Removing Observer"));
  if (!mObservers.RemoveElement(aObserver)) {
    LOG(("LOadManager - Element to remove not found"));
  }
}


}