Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Firefox/gfx/angle/checkout/src/common/   (Browser von der Mozilla Stiftung Version 136.0.1©)  Datei vom 10.2.2025 mit Größe 14 kB image not shown  

Quelle  SynchronizedValue.h   Sprache: C

 
//
// Copyright 2021 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// SynchronizedValue.h:
//   A class that ensures that the correct mutex is locked when the encapsulated data is accessed.
//   Based on boost::synchronized_value, which probably becomes part of the next C++ standard.
// https://www.boost.org/doc/libs/1_76_0/doc/html/thread/sds.html#thread.sds.synchronized_valuesxxx

#ifndef COMMON_SYNCHRONIZEDVALUE_H_
#define COMMON_SYNCHRONIZEDVALUE_H_

#include "common/debug.h"

#include <mutex>
#include <type_traits>

namespace angle
{

template <typename T, typename Lockable = std::mutex>
class ConstStrictLockPtr
{
  public:
    using value_type = T;
    using mutex_type = Lockable;

    ConstStrictLockPtr(const T &value, Lockable &mutex) : mLock(mutex), mValue(value) {}
    ConstStrictLockPtr(const T &value, Lockable &mutex, std::adopt_lock_t) noexcept
        : mLock(mutex, std::adopt_lock), mValue(value)
    {}

    ConstStrictLockPtr(ConstStrictLockPtr &&other) noexcept
        : mLock(std::move(other.mLock)), mValue(other.mValue)
    {}

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

    ~ConstStrictLockPtr() = default;

    const T *operator->() const { return &mValue; }
    const T &operator*() const { return mValue; }

  protected:
    std::unique_lock<Lockable> mLock;
    T const &mValue;
};

template <typename T, typename Lockable = std::mutex>
class StrictLockPtr : public ConstStrictLockPtr<T, Lockable>
{
  private:
    using BaseType = ConstStrictLockPtr<T, Lockable>;

  public:
    StrictLockPtr(T &value, Lockable &mutex) : BaseType(value, mutex) {}
    StrictLockPtr(T &value, Lockable &mutex, std::adopt_lock_t) noexcept
        : BaseType(value, mutex, std::adopt_lock)
    {}

    StrictLockPtr(StrictLockPtr &&other) noexcept
        : BaseType(std::move(static_cast<BaseType &&>(other)))
    {}

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

    ~StrictLockPtr() = default;

    T *operator->() { return const_cast<T *>(&this->mValue); }
    T &operator*() { return const_cast<T &>(this->mValue); }
};

template <typename SV>
struct SynchronizedValueStrictLockPtr
{
    using type = StrictLockPtr<typename SV::value_type, typename SV::mutex_type>;
};

template <typename SV>
struct SynchronizedValueStrictLockPtr<const SV>
{
    using type = ConstStrictLockPtr<typename SV::value_type, typename SV::mutex_type>;
};

template <typename T, typename Lockable = std::mutex>
class ConstUniqueLockPtr : public std::unique_lock<Lockable>
{
  private:
    using BaseType = std::unique_lock<Lockable>;

  public:
    using value_type = T;
    using mutex_type = Lockable;

    ConstUniqueLockPtr(const T &value, Lockable &mutex) : BaseType(mutex), mValue(value) {}
    ConstUniqueLockPtr(const T &value, Lockable &mutex, std::adopt_lock_t) noexcept
        : BaseType(mutex, std::adopt_lock), mValue(value)
    {}
    ConstUniqueLockPtr(const T &value, Lockable &mutex, std::defer_lock_t) noexcept
        : BaseType(mutex, std::defer_lock), mValue(value)
    {}
    ConstUniqueLockPtr(const T &value, Lockable &mutex, std::try_to_lock_t) noexcept
        : BaseType(mutex, std::try_to_lock), mValue(value)
    {}

    ConstUniqueLockPtr(ConstUniqueLockPtr &&other) noexcept
        : BaseType(std::move(static_cast<BaseType &&>(other))), mValue(other.mValue)
    {}

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

    ~ConstUniqueLockPtr() = default;

    const T *operator->() const
    {
        ASSERT(this->owns_lock());
        return &mValue;
    }
    const T &operator*() const
    {
        ASSERT(this->owns_lock());
        return mValue;
    }

  protected:
    T const &mValue;
};

template <typename T, typename Lockable = std::mutex>
class UniqueLockPtr : public ConstUniqueLockPtr<T, Lockable>
{
  private:
    using BaseType = ConstUniqueLockPtr<T, Lockable>;

  public:
    UniqueLockPtr(T &value, Lockable &mutex) : BaseType(value, mutex) {}
    UniqueLockPtr(T &value, Lockable &mutex, std::adopt_lock_t) noexcept
        : BaseType(value, mutex, std::adopt_lock)
    {}
    UniqueLockPtr(T &value, Lockable &mutex, std::defer_lock_t) noexcept
        : BaseType(value, mutex, std::defer_lock)
    {}
    UniqueLockPtr(T &value, Lockable &mutex, std::try_to_lock_t) noexcept
        : BaseType(value, mutex, std::try_to_lock)
    {}

    UniqueLockPtr(UniqueLockPtr &&other) noexcept
        : BaseType(std::move(static_cast<BaseType &&>(other)))
    {}

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

    ~UniqueLockPtr() = default;

    T *operator->()
    {
        ASSERT(this->owns_lock());
        return const_cast<T *>(&this->mValue);
    }
    T &operator*()
    {
        ASSERT(this->owns_lock());
        return const_cast<T &>(this->mValue);
    }
};

template <typename SV>
struct SynchronizedValueUniqueLockPtr
{
    using type = UniqueLockPtr<typename SV::value_type, typename SV::mutex_type>;
};

template <typename SV>
struct SynchronizedValueUniqueLockPtr<const SV>
{
    using type = ConstUniqueLockPtr<typename SV::value_type, typename SV::mutex_type>;
};

template <typename T, typename Lockable = std::mutex>
class SynchronizedValue
{
  public:
    using value_type = T;
    using mutex_type = Lockable;

    SynchronizedValue() noexcept(std::is_nothrow_default_constructible<T>::value) : mValue() {}

    SynchronizedValue(const T &other) noexcept(std::is_nothrow_copy_constructible<T>::value)
        : mValue(other)
    {}

    SynchronizedValue(T &&other) noexcept(std::is_nothrow_move_constructible<T>::value)
        : mValue(std::move(other))
    {}

    template <typename... Args>
    SynchronizedValue(Args &&... args) noexcept(noexcept(T(std::forward<Args>(args)...)))
        : mValue(std::forward<Args>(args)...)
    {}

    SynchronizedValue(const SynchronizedValue &other)
    {
        std::lock_guard<Lockable> lock(other.mMutex);
        mValue = other.mValue;
    }

    SynchronizedValue(SynchronizedValue &&other)
    {
        std::lock_guard<Lockable> lock(other.mMutex);
        mValue = std::move(other.mValue);
    }

    SynchronizedValue &operator=(const SynchronizedValue &other)
    {
        if (&other != this)
        {
            std::unique_lock<Lockable> lock1(mMutex, std::defer_lock);
            std::unique_lock<Lockable> lock2(other.mMutex, std::defer_lock);
            std::lock(lock1, lock2);
            mValue = other.mValue;
        }
        return *this;
    }

    SynchronizedValue &operator=(SynchronizedValue &&other)
    {
        if (&other != this)
        {
            std::unique_lock<Lockable> lock1(mMutex, std::defer_lock);
            std::unique_lock<Lockable> lock2(other.mMutex, std::defer_lock);
            std::lock(lock1, lock2);
            mValue = std::move(other.mValue);
        }
        return *this;
    }

    SynchronizedValue &operator=(const T &value)
    {
        {
            std::lock_guard<Lockable> lock(mMutex);
            mValue = value;
        }
        return *this;
    }

    SynchronizedValue &operator=(T &&value)
    {
        {
            std::lock_guard<Lockable> lock(mMutex);
            mValue = std::move(value);
        }
        return *this;
    }

    T get() const
    {
        std::lock_guard<Lockable> lock(mMutex);
        return mValue;
    }

    explicit operator T() const { return get(); }

    void swap(SynchronizedValue &other)
    {
        if (this == &other)
        {
            return;
        }
        std::unique_lock<Lockable> lock1(mMutex, std::defer_lock);
        std::unique_lock<Lockable> lock2(other.mMutex, std::defer_lock);
        std::lock(lock1, lock2);
        std::swap(mValue, other.mValue);
    }

    void swap(T &other)
    {
        std::lock_guard<Lockable> lock(mMutex);
        std::swap(mValue, other);
    }

    StrictLockPtr<T, Lockable> operator->() { return StrictLockPtr<T, Lockable>(mValue, mMutex); }
    ConstStrictLockPtr<T, Lockable> operator->() const
    {
        return ConstStrictLockPtr<T, Lockable>(mValue, mMutex);
    }

    StrictLockPtr<T, Lockable> synchronize() { return StrictLockPtr<T, Lockable>(mValue, mMutex); }
    ConstStrictLockPtr<T, Lockable> synchronize() const
    {
        return ConstStrictLockPtr<T, Lockable>(mValue, mMutex);
    }

    UniqueLockPtr<T, Lockable> unique_synchronize()
    {
        return UniqueLockPtr<T, Lockable>(mValue, mMutex);
    }
    ConstUniqueLockPtr<T, Lockable> unique_synchronize() const
    {
        return ConstUniqueLockPtr<T, Lockable>(mValue, mMutex);
    }

    UniqueLockPtr<T, Lockable> defer_synchronize() noexcept
    {
        return UniqueLockPtr<T, Lockable>(mValue, mMutex, std::defer_lock);
    }
    ConstUniqueLockPtr<T, Lockable> defer_synchronize() const noexcept
    {
        return ConstUniqueLockPtr<T, Lockable>(mValue, mMutex, std::defer_lock);
    }

    UniqueLockPtr<T, Lockable> try_to_synchronize() noexcept
    {
        return UniqueLockPtr<T, Lockable>(mValue, mMutex, std::try_to_lock);
    }
    ConstUniqueLockPtr<T, Lockable> try_to_synchronize() const noexcept
    {
        return ConstUniqueLockPtr<T, Lockable>(mValue, mMutex, std::try_to_lock);
    }

    UniqueLockPtr<T, Lockable> adopt_synchronize() noexcept
    {
        return UniqueLockPtr<T, Lockable>(mValue, mMutex, std::adopt_lock);
    }
    ConstUniqueLockPtr<T, Lockable> adopt_synchronize() const noexcept
    {
        return ConstUniqueLockPtr<T, Lockable>(mValue, mMutex, std::adopt_lock);
    }

    class DerefValue
    {
      public:
        DerefValue(DerefValue &&other) : mLock(std::move(other.mLock)), mValue(other.mValue) {}

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

        operator T &() { return mValue; }

        DerefValue &operator=(const T &other)
        {
            mValue = other;
            return *this;
        }

      private:
        explicit DerefValue(SynchronizedValue &outer) : mLock(outer.mMutex), mValue(outer.mValue) {}

        std::unique_lock<Lockable> mLock;
        T &mValue;

        friend class SynchronizedValue;
    };

    class ConstDerefValue
    {
      public:
        ConstDerefValue(ConstDerefValue &&other)
            : mLock(std::move(other.mLock)), mValue(other.mValue)
        {}

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

        operator const T &() { return mValue; }

      private:
        explicit ConstDerefValue(const SynchronizedValue &outer)
            : mLock(outer.mMutex), mValue(outer.mValue)
        {}

        std::unique_lock<Lockable> mLock;
        const T &mValue;

        friend class SynchronizedValue;
    };

    DerefValue operator*() { return DerefValue(*this); }
    ConstDerefValue operator*() const { return ConstDerefValue(*this); }

    template <typename OStream>
    void save(OStream &os) const
    {
        std::lock_guard<Lockable> lock(mMutex);
        os << mValue;
    }

    template <typename IStream>
    void load(IStream &is)
    {
        std::lock_guard<Lockable> lock(mMutex);
        is >> mValue;
    }

    bool operator==(const SynchronizedValue &other) const
    {
        std::unique_lock<Lockable> lock1(mMutex, std::defer_lock);
        std::unique_lock<Lockable> lock2(other.mMutex, std::defer_lock);
        std::lock(lock1, lock2);
        return mValue == other.mValue;
    }

    bool operator!=(const SynchronizedValue &other) const
    {
        std::unique_lock<Lockable> lock1(mMutex, std::defer_lock);
        std::unique_lock<Lockable> lock2(other.mMutex, std::defer_lock);
        std::lock(lock1, lock2);
        return mValue != other.mValue;
    }

    bool operator<(const SynchronizedValue &other) const
    {
        std::unique_lock<Lockable> lock1(mMutex, std::defer_lock);
        std::unique_lock<Lockable> lock2(other.mMutex, std::defer_lock);
        std::lock(lock1, lock2);
        return mValue < other.mValue;
    }

    bool operator>(const SynchronizedValue &other) const
    {
        std::unique_lock<Lockable> lock1(mMutex, std::defer_lock);
        std::unique_lock<Lockable> lock2(other.mMutex, std::defer_lock);
        std::lock(lock1, lock2);
        return mValue > other.mValue;
    }

    bool operator<=(const SynchronizedValue &other) const
    {
        std::unique_lock<Lockable> lock1(mMutex, std::defer_lock);
        std::unique_lock<Lockable> lock2(other.mMutex, std::defer_lock);
        std::lock(lock1, lock2);
        return mValue <= other.mValue;
    }

    bool operator>=(const SynchronizedValue &other) const
    {
        std::unique_lock<Lockable> lock1(mMutex, std::defer_lock);
        std::unique_lock<Lockable> lock2(other.mMutex, std::defer_lock);
        std::lock(lock1, lock2);
        return mValue >= other.mValue;
    }

    bool operator==(const T &other) const
    {
        std::lock_guard<Lockable> lock(mMutex);
        return mValue == other;
    }

    bool operator!=(const T &other) const
    {
        std::lock_guard<Lockable> lock(mMutex);
        return mValue != other;
    }

    bool operator<(const T &other) const
    {
        std::lock_guard<Lockable> lock(mMutex);
        return mValue < other;
    }

    bool operator>(const T &other) const
    {
        std::lock_guard<Lockable> lock(mMutex);
        return mValue > other;
    }

    bool operator<=(const T &other) const
    {
        std::lock_guard<Lockable> lock(mMutex);
        return mValue <= other;
    }

    bool operator>=(const T &other) const
    {
        std::lock_guard<Lockable> lock(mMutex);
        return mValue >= other;
    }

  private:
    T mValue;
    mutable Lockable mMutex;
};

template <typename OStream, typename T, typename L>
inline OStream &operator<<(OStream &os, SynchronizedValue<T, L> const &sv)
{
    sv.save(os);
    return os;
}

template <typename IStream, typename T, typename L>
inline IStream &operator>>(IStream &is, SynchronizedValue<T, L> &sv)
{
    sv.load(is);
    return is;
}

template <typename T, typename L>
bool operator==(const T &lhs, const SynchronizedValue<T, L> &rhs)
{
    return rhs == lhs;
}

template <typename T, typename L>
bool operator!=(const T &lhs, const SynchronizedValue<T, L> &rhs)
{
    return rhs != lhs;
}

template <typename T, typename L>
bool operator<(const T &lhs, const SynchronizedValue<T, L> &rhs)
{
    return rhs < lhs;
}

template <typename T, typename L>
bool operator>(const T &lhs, const SynchronizedValue<T, L> &rhs)
{
    return rhs > lhs;
}

template <typename T, typename L>
bool operator<=(const T &lhs, const SynchronizedValue<T, L> &rhs)
{
    return rhs <= lhs;
}

template <typename T, typename L>
bool operator>=(const T &lhs, const SynchronizedValue<T, L> &rhs)
{
    return rhs >= lhs;
}

}  // namespace angle

#endif  // COMMON_SYNCHRONIZEDVALUE_H_

Messung V0.5
C=98 H=100 G=98

¤ Dauer der Verarbeitung: 0.14 Sekunden  (vorverarbeitet)  ¤

*© 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.