#pragma once
#include <util/generic/ptr.h>
#include <util/system/rwlock.h>


template <class C, class CLock = TRWMutex, class CReadGuard = TReadGuard>
class TGuardedPtr: public TPointerBase<TGuardedPtr<C, CLock, CReadGuard>, C> {
private:
    C* T_;
    TSimpleSharedPtr<CReadGuard> Guard;
public:
    TGuardedPtr(C* t, CLock& lock) noexcept
        : T_(t)
        , Guard(new CReadGuard(lock))
    {

    }

    C* Get() const {
        return T_;
    }
};

template <class C, class CLock = TRWMutex, class CReadGuard = TReadGuard, class CWriteGuard = TWriteGuard>
class TGuardedOwner {
private:
    CLock Lock;
    C* T_;
    TGuardedOwner(const TGuardedOwner&);
    TGuardedOwner& operator= (const TGuardedOwner&);
public:
    TGuardedOwner(C* t, CLock&) noexcept
        : T_(t)
    {

    }

    TGuardedPtr<C, CLock, CReadGuard> Get() const {
        return TGuardedPtr<C, CLock, CReadGuard>(T_, Lock);
    }

    ~TGuardedOwner() {
        CWriteGuard g(Lock);
        delete T_;
    }
};
