#pragma once #include "intrusive_ptr.h" #include "range.h" #include "ref_counted.h" #include namespace NYT { //////////////////////////////////////////////////////////////////////////////// template class TCompactVector; //! TRange with ownership semantics. template class TSharedRange : public TRange { public: using THolderPtr = TRefCountedPtr; //! Constructs a null TSharedRange. TSharedRange() { } //! Constructs a TSharedRange from TRange. TSharedRange(TRange range, THolderPtr holder) : TRange(range) , Holder_(std::move(holder)) { } //! Constructs a TSharedRange from a pointer and length. TSharedRange(const T* data, size_t length, THolderPtr holder) : TRange(data, length) , Holder_(std::move(holder)) { } //! Constructs a TSharedRange from a range. TSharedRange(const T* begin, const T* end, THolderPtr holder) : TRange(begin, end) , Holder_(std::move(holder)) { } //! Constructs a TSharedRange from a TCompactVector. template TSharedRange(const TCompactVector& elements, THolderPtr holder) : TRange(elements) , Holder_(std::move(holder)) { } //! Constructs a TSharedRange from an std::vector. TSharedRange(const std::vector& elements, THolderPtr holder) : TRange(elements) , Holder_(std::move(holder)) { } //! Constructs a TSharedRange from a C array. template TSharedRange(const T (& elements)[N], THolderPtr holder) : TRange(elements) , Holder_(std::move(holder)) { } void Reset() { TRange::Data_ = nullptr; TRange::Length_ = 0; Holder_.Reset(); } TSharedRange Slice(size_t startOffset, size_t endOffset) const { YT_ASSERT(startOffset <= this->Size()); YT_ASSERT(endOffset >= startOffset && endOffset <= this->Size()); return TSharedRange(this->Begin() + startOffset, endOffset - startOffset, Holder_); } TSharedRange Slice(const T* begin, const T* end) const { YT_ASSERT(begin >= this->Begin()); YT_ASSERT(end <= this->End()); return TSharedRange(begin, end, Holder_); } const THolderPtr& GetHolder() const { return Holder_; } THolderPtr&& ReleaseHolder() { return std::move(Holder_); } protected: THolderPtr Holder_; }; //////////////////////////////////////////////////////////////////////////////// //! Constructs a combined holder instance by taking ownership of a given list of holders. template TRefCountedPtr MakeCompositeHolder(THolders&&... holders) { struct THolder : public TRefCounted { std::tuple::type...> Holders; }; auto holder = New(); holder->Holders = std::tuple(std::forward(holders)...); return holder; } template TSharedRange DoMakeSharedRange(TContainer&& elements, THolders&&... holders) { struct THolder : public TRefCounted { typename std::decay::type Elements; std::tuple::type...> Holders; }; auto holder = New(); holder->Holders = std::tuple(std::forward(holders)...); holder->Elements = std::forward(elements); auto range = MakeRange(holder->Elements); return TSharedRange(range, std::move(holder)); } //! Constructs a TSharedRange by taking ownership of an std::vector. template TSharedRange MakeSharedRange(std::vector&& elements, THolders&&... holders) { return DoMakeSharedRange(std::move(elements), std::forward(holders)...); } //! Constructs a TSharedRange by taking ownership of an TCompactVector. template TSharedRange MakeSharedRange(TCompactVector&& elements, THolders&&... holders) { return DoMakeSharedRange(std::move(elements), std::forward(holders)...); } //! Constructs a TSharedRange by copying an std::vector. template TSharedRange MakeSharedRange(const std::vector& elements, THolders&&... holders) { return DoMakeSharedRange(elements, std::forward(holders)...); } template TSharedRange MakeSharedRange(TRange range, THolders&&... holders) { return TSharedRange(range, MakeCompositeHolder(std::forward(holders)...)); } template TSharedRange MakeSharedRange(TRange range, TIntrusivePtr holder) { return TSharedRange(range, std::move(holder)); } template TSharedRange ReinterpretCastRange(const TSharedRange& range) { static_assert(sizeof(T) == sizeof(U), "T and U must have equal sizes."); return TSharedRange(reinterpret_cast(range.Begin()), range.Size(), range.GetHolder()); }; //////////////////////////////////////////////////////////////////////////////// //! TMutableRange with ownership semantics. //! Use with caution :) template class TSharedMutableRange : public TMutableRange { public: using THolderPtr = TRefCountedPtr; //! Constructs a null TSharedMutableRange. TSharedMutableRange() { } //! Constructs a TSharedMutableRange from TMutableRange. TSharedMutableRange(TMutableRange range, THolderPtr holder) : TMutableRange(range) , Holder_(std::move(holder)) { } //! Constructs a TSharedMutableRange from a pointer and length. TSharedMutableRange(T* data, size_t length, THolderPtr holder) : TMutableRange(data, length) , Holder_(std::move(holder)) { } //! Constructs a TSharedMutableRange from a range. TSharedMutableRange(T* begin, T* end, THolderPtr holder) : TMutableRange(begin, end) , Holder_(std::move(holder)) { } //! Constructs a TSharedMutableRange from a TCompactVector. template TSharedMutableRange(TCompactVector& elements, THolderPtr holder) : TMutableRange(elements) , Holder_(std::move(holder)) { } //! Constructs a TSharedMutableRange from an std::vector. TSharedMutableRange(std::vector& elements, THolderPtr holder) : TMutableRange(elements) , Holder_(std::move(holder)) { } //! Constructs a TSharedMutableRange from a C array. template TSharedMutableRange(T (& elements)[N], THolderPtr holder) : TMutableRange(elements) , Holder_(std::move(holder)) { } void Reset() { TRange::Data_ = nullptr; TRange::Length_ = 0; Holder_.Reset(); } TSharedMutableRange Slice(size_t startOffset, size_t endOffset) const { YT_ASSERT(startOffset <= this->Size()); YT_ASSERT(endOffset >= startOffset && endOffset <= this->Size()); return TSharedMutableRange(this->Begin() + startOffset, endOffset - startOffset, Holder_); } TSharedMutableRange Slice(T* begin, T* end) const { YT_ASSERT(begin >= this->Begin()); YT_ASSERT(end <= this->End()); return TSharedMutableRange(begin, end, Holder_); } THolderPtr GetHolder() const { return Holder_; } THolderPtr&& ReleaseHolder() { return std::move(Holder_); } protected: THolderPtr Holder_; }; template TSharedMutableRange DoMakeSharedMutableRange(TContainer&& elements, THolders&&... holders) { struct THolder : public TRefCounted { typename std::decay::type Elements; std::tuple::type...> Holders; }; auto holder = New(); holder->Holders = std::tuple(std::forward(holders)...); holder->Elements = std::forward(elements); auto range = TMutableRange(holder->Elements); return TSharedMutableRange(range, holder); } //! Constructs a TSharedMutableRange by taking ownership of an std::vector. template TSharedMutableRange MakeSharedMutableRange(std::vector&& elements, THolders&&... holders) { return DoMakeSharedMutableRange(std::move(elements), std::forward(holders)...); } //////////////////////////////////////////////////////////////////////////////// } // namespace NYT