Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Firefox/mozglue/baseprofiler/public/   (Browser von der Mozilla Stiftung Version 136.0.1©)  Datei vom 10.2.2025 mit Größe 9 kB image not shown  

Quelle  BaseProfilerDetail.h   Sprache: C

 
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* 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/. */


// Internal Base Profiler utilities.

#ifndef BaseProfilerDetail_h
#define BaseProfilerDetail_h

#include "mozilla/Atomics.h"
#include "mozilla/Attributes.h"
#include "mozilla/Maybe.h"
#include "mozilla/PlatformMutex.h"
#include "mozilla/PlatformRWLock.h"
#include "mozilla/BaseProfilerUtils.h"

namespace mozilla {
namespace baseprofiler {

namespace detail {

// Thin shell around mozglue PlatformMutex, for Base Profiler internal use.
class MOZ_CAPABILITY("mutex") BaseProfilerMutex
    : private ::mozilla::detail::MutexImpl {
 public:
  BaseProfilerMutex() : ::mozilla::detail::MutexImpl() {}
  explicit BaseProfilerMutex(const char* aName)
      : ::mozilla::detail::MutexImpl(), mName(aName) {}

  BaseProfilerMutex(const BaseProfilerMutex&) = delete;
  BaseProfilerMutex& operator=(const BaseProfilerMutex&) = delete;
  BaseProfilerMutex(BaseProfilerMutex&&) = delete;
  BaseProfilerMutex& operator=(BaseProfilerMutex&&) = delete;

#ifdef DEBUG
  ~BaseProfilerMutex() {
    MOZ_ASSERT(!BaseProfilerThreadId::FromNumber(mOwningThreadId).IsSpecified(),
               "BaseProfilerMutex should have been unlocked when destroyed");
  }
#endif  // DEBUG

  [[nodiscard]] bool IsLockedOnCurrentThread() const {
    return BaseProfilerThreadId::FromNumber(mOwningThreadId) ==
           baseprofiler::profiler_current_thread_id();
  }

  void AssertCurrentThreadOwns() const MOZ_ASSERT_CAPABILITY(this) {
    MOZ_ASSERT(IsLockedOnCurrentThread());
  }

  void Lock() MOZ_CAPABILITY_ACQUIRE() {
    const BaseProfilerThreadId tid = baseprofiler::profiler_current_thread_id();
    MOZ_ASSERT(tid.IsSpecified());
    MOZ_ASSERT(!IsLockedOnCurrentThread(), "Recursive locking");
    ::mozilla::detail::MutexImpl::lock();
    MOZ_ASSERT(!BaseProfilerThreadId::FromNumber(mOwningThreadId).IsSpecified(),
               "Not unlocked properly");
    mOwningThreadId = tid.ToNumber();
  }

  [[nodiscard]] bool TryLock() MOZ_TRY_ACQUIRE(true) {
    const BaseProfilerThreadId tid = baseprofiler::profiler_current_thread_id();
    MOZ_ASSERT(tid.IsSpecified());
    MOZ_ASSERT(!IsLockedOnCurrentThread(), "Recursive locking");
    if (!::mozilla::detail::MutexImpl::tryLock()) {
      // Failed to lock, nothing more to do.
      return false;
    }
    MOZ_ASSERT(!BaseProfilerThreadId::FromNumber(mOwningThreadId).IsSpecified(),
               "Not unlocked properly");
    mOwningThreadId = tid.ToNumber();
    return true;
  }

  void Unlock() MOZ_CAPABILITY_RELEASE() {
    MOZ_ASSERT(IsLockedOnCurrentThread(), "Unlocking when not locked here");
    // We're still holding the mutex here, so it's safe to just reset
    // `mOwningThreadId`.
    mOwningThreadId = BaseProfilerThreadId{}.ToNumber();
    ::mozilla::detail::MutexImpl::unlock();
  }

  const char* GetName() const { return mName; }

 private:
  // Thread currently owning the lock, or 0.
  // Atomic because it may be read at any time independent of the mutex.
  // Relaxed because threads only need to know if they own it already, so:
  // - If it's their id, only *they* wrote that value with a locked mutex.
  // - If it's different from their thread id it doesn't matter what other
  //   number it is (0 or another id) and that it can change again at any time.
  Atomic<typename BaseProfilerThreadId::NumberType, MemoryOrdering::Relaxed>
      mOwningThreadId;

  const char* mName = nullptr;
};

// RAII class to lock a mutex.
class MOZ_RAII BaseProfilerAutoLock {
 public:
  explicit BaseProfilerAutoLock(BaseProfilerMutex& aMutex) : mMutex(aMutex) {
    mMutex.Lock();
  }

  BaseProfilerAutoLock(const BaseProfilerAutoLock&) = delete;
  BaseProfilerAutoLock& operator=(const BaseProfilerAutoLock&) = delete;
  BaseProfilerAutoLock(BaseProfilerAutoLock&&) = delete;
  BaseProfilerAutoLock& operator=(BaseProfilerAutoLock&&) = delete;

  ~BaseProfilerAutoLock() { mMutex.Unlock(); }

 private:
  BaseProfilerMutex& mMutex;
};

// Thin shell around mozglue PlatformMutex, for Base Profiler internal use.
// Actual mutex may be disabled at construction time.
class BaseProfilerMaybeMutex : private ::mozilla::detail::MutexImpl {
 public:
  explicit BaseProfilerMaybeMutex(bool aActivate) {
    if (aActivate) {
      mMaybeMutex.emplace();
    }
  }

  BaseProfilerMaybeMutex(const BaseProfilerMaybeMutex&) = delete;
  BaseProfilerMaybeMutex& operator=(const BaseProfilerMaybeMutex&) = delete;
  BaseProfilerMaybeMutex(BaseProfilerMaybeMutex&&) = delete;
  BaseProfilerMaybeMutex& operator=(BaseProfilerMaybeMutex&&) = delete;

  ~BaseProfilerMaybeMutex() = default;

  bool IsActivated() const { return mMaybeMutex.isSome(); }

  [[nodiscard]] bool IsActivatedAndLockedOnCurrentThread() const {
    if (!IsActivated()) {
      // Not activated, so we can never be locked.
      return false;
    }
    return mMaybeMutex->IsLockedOnCurrentThread();
  }

  void AssertCurrentThreadOwns() const {
#ifdef DEBUG
    if (IsActivated()) {
      mMaybeMutex->AssertCurrentThreadOwns();
    }
#endif  // DEBUG
  }

  MOZ_PUSH_IGNORE_THREAD_SAFETY
  void Lock() {
    if (IsActivated()) {
      mMaybeMutex->Lock();
    }
  }

  void Unlock() {
    if (IsActivated()) {
      mMaybeMutex->Unlock();
    }
  }
  MOZ_POP_THREAD_SAFETY

 private:
  Maybe<BaseProfilerMutex> mMaybeMutex;
};

// RAII class to lock a mutex.
class MOZ_RAII BaseProfilerMaybeAutoLock {
 public:
  explicit BaseProfilerMaybeAutoLock(BaseProfilerMaybeMutex& aMaybeMutex)
      : mMaybeMutex(aMaybeMutex) {
    mMaybeMutex.Lock();
  }

  BaseProfilerMaybeAutoLock(const BaseProfilerMaybeAutoLock&) = delete;
  BaseProfilerMaybeAutoLock& operator=(const BaseProfilerMaybeAutoLock&) =
      delete;
  BaseProfilerMaybeAutoLock(BaseProfilerMaybeAutoLock&&) = delete;
  BaseProfilerMaybeAutoLock& operator=(BaseProfilerMaybeAutoLock&&) = delete;

  ~BaseProfilerMaybeAutoLock() { mMaybeMutex.Unlock(); }

 private:
  BaseProfilerMaybeMutex& mMaybeMutex;
};

class BaseProfilerSharedMutex : public ::mozilla::detail::RWLockImpl {
 public:
#ifdef DEBUG
  ~BaseProfilerSharedMutex() {
    MOZ_ASSERT(!BaseProfilerThreadId::FromNumber(mOwningThreadId).IsSpecified(),
               "BaseProfilerMutex should have been unlocked when destroyed");
  }
#endif  // DEBUG

  [[nodiscard]] bool IsLockedExclusiveOnCurrentThread() const {
    return BaseProfilerThreadId::FromNumber(mOwningThreadId) ==
           baseprofiler::profiler_current_thread_id();
  }

  void LockExclusive() {
    const BaseProfilerThreadId tid = baseprofiler::profiler_current_thread_id();
    MOZ_ASSERT(tid.IsSpecified());
    MOZ_ASSERT(!IsLockedExclusiveOnCurrentThread(), "Recursive locking");
    ::mozilla::detail::RWLockImpl::writeLock();
    MOZ_ASSERT(!BaseProfilerThreadId::FromNumber(mOwningThreadId).IsSpecified(),
               "Not unlocked properly");
    mOwningThreadId = tid.ToNumber();
  }

  void UnlockExclusive() {
    MOZ_ASSERT(IsLockedExclusiveOnCurrentThread(),
               "Unlocking when not locked here");
    // We're still holding the mutex here, so it's safe to just reset
    // `mOwningThreadId`.
    mOwningThreadId = BaseProfilerThreadId{}.ToNumber();
    writeUnlock();
  }

  void LockShared() { readLock(); }

  void UnlockShared() { readUnlock(); }

 private:
  // Thread currently owning the exclusive lock, or 0.
  // Atomic because it may be read at any time independent of the mutex.
  // Relaxed because threads only need to know if they own it already, so:
  // - If it's their id, only *they* wrote that value with a locked mutex.
  // - If it's different from their thread id it doesn't matter what other
  //   number it is (0 or another id) and that it can change again at any time.
  Atomic<typename BaseProfilerThreadId::NumberType, MemoryOrdering::Relaxed>
      mOwningThreadId;
};

// RAII class to lock a shared mutex exclusively.
class MOZ_RAII BaseProfilerAutoLockExclusive {
 public:
  explicit BaseProfilerAutoLockExclusive(BaseProfilerSharedMutex& aSharedMutex)
      : mSharedMutex(aSharedMutex) {
    mSharedMutex.LockExclusive();
  }

  BaseProfilerAutoLockExclusive(const BaseProfilerAutoLockExclusive&) = delete;
  BaseProfilerAutoLockExclusive& operator=(
      const BaseProfilerAutoLockExclusive&) = delete;
  BaseProfilerAutoLockExclusive(BaseProfilerAutoLockExclusive&&) = delete;
  BaseProfilerAutoLockExclusive& operator=(BaseProfilerAutoLockExclusive&&) =
      delete;

  ~BaseProfilerAutoLockExclusive() { mSharedMutex.UnlockExclusive(); }

 private:
  BaseProfilerSharedMutex& mSharedMutex;
};

// RAII class to lock a shared mutex non-exclusively, other
// BaseProfilerAutoLockShared's may happen in other threads.
class MOZ_RAII BaseProfilerAutoLockShared {
 public:
  explicit BaseProfilerAutoLockShared(BaseProfilerSharedMutex& aSharedMutex)
      : mSharedMutex(aSharedMutex) {
    mSharedMutex.LockShared();
  }

  BaseProfilerAutoLockShared(const BaseProfilerAutoLockShared&) = delete;
  BaseProfilerAutoLockShared& operator=(const BaseProfilerAutoLockShared&) =
      delete;
  BaseProfilerAutoLockShared(BaseProfilerAutoLockShared&&) = delete;
  BaseProfilerAutoLockShared& operator=(BaseProfilerAutoLockShared&&) = delete;

  ~BaseProfilerAutoLockShared() { mSharedMutex.UnlockShared(); }

 private:
  BaseProfilerSharedMutex& mSharedMutex;
};

}  // namespace detail
}  // namespace baseprofiler
}  // namespace mozilla

#endif  // BaseProfilerDetail_h

Messung V0.5
C=98 H=90 G=94

¤ Dauer der Verarbeitung: 0.4 Sekunden  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

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.