Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Firefox/xpcom/threads/   (Firefox Browser Version 153.0.1©)  Datei vom 27.6.2026 mit Größe 6 kB image not shown  

Quelle  SharedThreadPool.cpp

  Sprache: C
 

/* 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 "mozilla/SharedThreadPool.h"

#include "mozilla/AppShutdown.h"
#include "mozilla/Logging.h"

#include "mozilla/AppShutdown.h"
#include "mozilla/Monitor.h"
#include "mozilla/ReentrantMonitor.h"
#include "mozilla/Services.h"
#include "mozilla/SpinEventLoopUntil.h"
#include "mozilla/StaticPtr.h"
#include "nsComponentManagerUtils.h"
#include "nsIObserver.h"
#include "nsIObserverService.h"
#include "nsIThreadManager.h"
#include "nsThreadPool.h"
#include "nsTHashMap.h"
#include "nsXPCOMCIDInternal.h"

static mozilla::LazyLogModule sSharedThreadPoolLog("SharedThreadPool");

#define STP_LOG(level, msg, ...) \
  MOZ_LOG_FMT(sSharedThreadPoolLog, level, msg, ##__VA_ARGS__)

namespace mozilla {

// Hash map, maps thread pool names to SharedThreadPool instances.
using PoolMap = nsTHashMap<nsCStringHashKey, RefPtr<SharedThreadPool>>;
static StaticMutex sPoolsMutex;
static StaticAutoPtr<PoolMap> sPools MOZ_GUARDED_BY(sPoolsMutex);
static bool sPoolsShutdownStarted MOZ_GUARDED_BY(sPoolsMutex) = false;

static already_AddRefed<nsIThreadPool> CreateThreadPool(const nsCString& aName,
                                                        uint32_t aThreadLimit) {
  nsCOMPtr<nsIThreadPool> pool = new nsThreadPool();

  nsresult rv = pool->SetName(aName);
  NS_ENSURE_SUCCESS(rv, nullptr);

  // Set the thread limits. Note that we don't rely on the
  // EnsureThreadLimitIsAtLeast() call below, as the default thread
  // limit is 4, and if aThreadLimit is less than 4 we'll end up with a
  // pool with 4 threads rather than what we expected; so we'll have
  // unexpected behaviour.
  rv = pool->SetThreadLimit(aThreadLimit);
  NS_ENSURE_SUCCESS(rv, nullptr);

  // Note that we just keep the DEFAULT_IDLE_THREAD_LIMIT (currently 1).

  // We keep any ever created SharedThreadPool until shutdown, but if
  // it's not used, its threads will go away after a short while.
  rv = pool->SetIdleThreadGraceTimeout(500);
  NS_ENSURE_SUCCESS(rv, nullptr);
  rv = pool->SetIdleThreadMaximumTimeout(5000);
  NS_ENSURE_SUCCESS(rv, nullptr);

  return pool.forget();
}

class SharedThreadPoolShutdownObserver : public nsIObserver {
 public:
  NS_DECL_ISUPPORTS
  NS_DECL_NSIOBSERVER
 protected:
  virtual ~SharedThreadPoolShutdownObserver() = default;
};

NS_IMPL_ISUPPORTS(SharedThreadPoolShutdownObserver, nsIObserver, nsISupports)

NS_IMETHODIMP
SharedThreadPoolShutdownObserver::Observe(nsISupports* aSubject,
                                          const char* aTopic,
                                          const char16_t* aData) {
  MOZ_RELEASE_ASSERT(!strcmp(aTopic, "xpcom-shutdown-threads"));

  // During shutdown we do not allow the creation of new functional
  // SharedThreadPools, but we do allow access to existing ones. This may lead
  // to the situation that a dispatch to a SharedThreadPool fails because its
  // underlying nsIThreadPool has already been shut down and is now defunct.
  // However, it allows code to safely retrieve and use the same pool it is
  // running on during shutdown.
  nsTArray<RefPtr<SharedThreadPool>> pools;
  {
    StaticMutexAutoLock lock(sPoolsMutex);
    sPoolsShutdownStarted = true;
    AppendToArray(pools, sPools->Values());
  }
  for (const auto& pool : pools) {
    // Note that nsThreadPool::Shutdown will annotate the crash report
    // if it hangs.
    STP_LOG(LogLevel::Debug, "Shutdown {}", fmt::ptr(pool.get()));
    pool->Shutdown();
  }
  {
    StaticMutexAutoLock lock(sPoolsMutex);
    sPools->Clear();
  }
  pools.Clear();
  return NS_OK;
}

void SharedThreadPool::InitStatics() {
  MOZ_ASSERT(NS_IsMainThread());
  StaticMutexAutoLock lock(sPoolsMutex);
  MOZ_ASSERT(!sPools);
  sPools = new nsTHashMap<nsCStringHashKey, RefPtr<SharedThreadPool>>();
  nsCOMPtr<nsIObserverService> obsService =
      mozilla::services::GetObserverService();
  nsCOMPtr<nsIObserver> obs = new SharedThreadPoolShutdownObserver();
  obsService->AddObserver(obs, "xpcom-shutdown-threads"false);
}

already_AddRefed<SharedThreadPool> SharedThreadPool::Get(
    StaticString aName, uint32_t aThreadLimit) {
  StaticMutexAutoLock lock(sPoolsMutex);
  MOZ_ASSERT(sPools);

  nsCString name(aName);
  return sPools->WithEntryHandle(
      name, [&](auto&& entry) -> already_AddRefed<SharedThreadPool> {
        RefPtr<SharedThreadPool> pool;
        if (entry) {
          pool = entry.Data();
          if (NS_FAILED(pool->EnsureThreadLimitIsAtLeast(aThreadLimit))) {
            NS_WARNING("Failed to set limits on thread pool");
          }
          STP_LOG(LogLevel::Debug, "Existing {} found for {}",
                  fmt::ptr(pool.get()), name);
        } else {
          sPoolsMutex.AssertCurrentThreadOwns();
          if (sPoolsShutdownStarted) {
            // Do not allow the creation of new shared pools during shutdown.
            return do_AddRef(new SharedThreadPool(nullptr));
          }

          nsCOMPtr<nsIThreadPool> threadPool(
              CreateThreadPool(name, aThreadLimit));
          if (NS_WARN_IF(!threadPool)) {
            return do_AddRef(new SharedThreadPool(nullptr));
          }
          pool = new SharedThreadPool(threadPool);
          // We do AddRef here and keep the pool alive in the hash map.
          entry.Insert(pool.get());
          STP_LOG(LogLevel::Debug, "New {} created for {}",
                  fmt::ptr(pool.get()), name);
        }

        return pool.forget();
      });
}

NS_IMPL_ISUPPORTS(SharedThreadPool, nsIThreadPool, nsIEventTarget)

SharedThreadPool::SharedThreadPool(nsIThreadPool* aPool) : mPool(aPool) {}

SharedThreadPool::~SharedThreadPool() = default;

nsresult SharedThreadPool::EnsureThreadLimitIsAtLeast(uint32_t aThreadLimit) {
  uint32_t existingLimit = 0;
  nsresult rv;

  rv = mPool->GetThreadLimit(&existingLimit);
  NS_ENSURE_SUCCESS(rv, rv);
  if (aThreadLimit > existingLimit) {
    rv = mPool->SetThreadLimit(aThreadLimit);
    NS_ENSURE_SUCCESS(rv, rv);
  }

  return NS_OK;
}

}  // namespace mozilla

#undef STP_LOG

Messung V0.5 in Prozent
C=89 H=95 G=91

¤ Dauer der Verarbeitung: 0.3 Sekunden  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

PVS Prover

Isabelle Prover

NIST Cobol Testsuite

Cephes Mathematical Library

Vienna Development Method

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.