read_protected.h

Back to Read protection

pastel/sys/

// Description: Read protection

#ifndef PASTELSYS_READ_PROTECTED_H
#define PASTELSYS_READ_PROTECTED_H

#include "pastel/sys/mytypes.h"
#include "pastel/sys/ensure.h"

#include <utility>
#include <memory>

namespace Pastel
{

    template <typename Type>
    class ReadProtected;

    template <typename Type>
    class ReadPtr
    {
    public:
        ReadPtr()
            : read_()
        {
        }

        ReadPtr(const ReadPtr& that)
            : read_(that.read_)
        {
        }

        ReadPtr(ReadPtr&& that)
            : read_(std::move(that.read_))
        {
        }

        template <typename That>
        bool operator==(const ReadPtr<That>& that) const
        {
            return get() == that.get();
        }

        template <typename That>
        bool operator!=(const ReadPtr<That>& that) const
        {
            return !(*this == that);
        }

        void swap(ReadPtr& that)
        {
            read_.swap(that.read_);
        }

        void clear()
        {
            read_.reset();
        }

        integer readCount() const
        {
            return read_.use_count();
        }

        const Type* get() const
        {
            return *read_;
        }

        const Type* operator->() const
        {
            return *read_;
        }

        const Type& operator*() const
        {
            return **read_;
        }

    private:
        friend class ReadProtected<Type>;

        explicit ReadPtr(const Type* that)
            : read_(new const Type*)
        {
            *read_ = that;
        }

        void swapPtr(ReadPtr& that)
        {
            ASSERT(read_ && that.read_);
            std::swap(*read_, *that.read_);
        }

        std::shared_ptr<const Type*> read_;
    };

    template <typename Type>
    class ReadProtected
    {
    public:
        explicit ReadProtected(const Type* that)
            : read_(that)
        {
        }

        ~ReadProtected()
        {
            readProtect();
        }

        void readProtect()
        {
            ENSURE_OP(readCount(), ==, 1);
        }

        integer readCount() const
        {
            return read_.readCount();
        }

        void swap(ReadProtected& that)
        {
            read_.swap(that.read_);
            read_.swapPtr(that.read_);
        }

        ReadPtr<Type> read() const
        {
            return read_;
        }

    private:
        ReadProtected();
        ReadProtected(ReadProtected&& that);
        ReadProtected(const ReadProtected& that);
        ReadProtected& operator=(ReadProtected that);

        ReadPtr<Type> read_;
    };

}

#endif