Program Listing for File synchronised.h

Return to documentation for file (include/core/mir/synchronised.h)

/*
 * Copyright © Canonical Ltd.
 *
 * This program is free software: you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License version 2 or 3,
 * as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#ifndef MIR_SYNCHRONISED_H_
#define MIR_SYNCHRONISED_H_

#include <mutex>

namespace mir
{

template<typename T>
class Synchronised
{
public:
    Synchronised() = default;
    Synchronised(T&& initial_value)
        : value{std::move(initial_value)}
    {
    }

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

    template<typename U>
    class LockedImpl
    {
    public:
        LockedImpl(LockedImpl&& from) noexcept
            : value{from.value},
              lock{std::move(from.lock)}
        {
            from.value = nullptr;
        }

        ~LockedImpl() = default;

        auto operator*() const -> U&
        {
            return *value;
        }

        auto operator->() const -> U*
        {
            return value;
        }

        void drop()
        {
            value = nullptr;
            lock.unlock();
        }

        template<typename Cv, typename Predicate>
        void wait(Cv& cv, Predicate stop_waiting)
        {
            cv.wait(lock, stop_waiting);
        }

    private:
        friend class Synchronised;
        LockedImpl(std::unique_lock<std::mutex>&& lock, U& value)
            : value{&value},
              lock{std::move(lock)}
        {
        }

        U* value;
        std::unique_lock<std::mutex> lock;
    };

    using Locked = LockedImpl<T>;
    auto lock() -> Locked
    {
        return LockedImpl<T>{std::unique_lock{mutex}, value};
    }

    using LockedView = LockedImpl<T const>;
    auto lock() const -> LockedView
    {
        return LockedImpl<T const>{std::unique_lock{mutex}, value};
    }
private:
    std::mutex mutable mutex;
    T value;
};

}

#endif //MIR_SYNCHRONISED_H_