Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 2 additions & 15 deletions include/tvm/ffi/container/array.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,18 +43,8 @@ namespace tvm {
namespace ffi {

/*! \brief Array node content in array */
class ArrayObj : public SeqBaseObj, public details::InplaceArrayBase<ArrayObj, TVMFFIAny> {
// InplaceArrayBase<ArrayObj, TVMFFIAny>'s destructor is compiled out because TVMFFIAny is
// trivial. SeqBaseObj::~SeqBaseObj() handles element destruction. Changing the ElemType to a
// non-trivial type would cause double-destruction.
static_assert(std::is_trivially_destructible_v<TVMFFIAny>,
"InplaceArrayBase<ArrayObj, TVMFFIAny> must use a trivially destructible "
"element type to avoid double-destruction with SeqBaseObj::~SeqBaseObj()");

class ArrayObj : public SeqBaseObj {
public:
// Bring SeqBaseObj names into ArrayObj scope to hide InplaceArrayBase's versions
using SeqBaseObj::operator[];
using SeqBaseObj::EmplaceInit;
/*!
* \brief Constructs a container and copy from another
* \param cap The capacity of the container
Expand Down Expand Up @@ -132,7 +122,7 @@ class ArrayObj : public SeqBaseObj, public details::InplaceArrayBase<ArrayObj, T
ObjectPtr<ArrayObj> p = make_inplace_array_object<ArrayObj, Any>(n);
p->TVMFFISeqCell::capacity = n;
p->TVMFFISeqCell::size = 0;
p->data = p->AddressOf(0);
p->data = reinterpret_cast<char*>(p.get()) + sizeof(ArrayObj);
p->data_deleter = nullptr;
return p;
}
Expand Down Expand Up @@ -161,9 +151,6 @@ class ArrayObj : public SeqBaseObj, public details::InplaceArrayBase<ArrayObj, T
/*! \brief Expansion factor of the Array */
static constexpr int64_t kIncFactor = 2;

// CRTP parent class
friend InplaceArrayBase<ArrayObj, Any>;

// Reference class
template <typename, typename>
friend class Array;
Expand Down
128 changes: 0 additions & 128 deletions include/tvm/ffi/container/container_details.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,134 +36,6 @@
namespace tvm {
namespace ffi {
namespace details {
/*!
* \brief Base template for classes with array like memory layout.
*
* It provides general methods to access the memory. The memory
* layout is ArrayType + [ElemType]. The alignment of ArrayType
* and ElemType is handled by the memory allocator.
*
* \tparam ArrayType The array header type, contains object specific metadata.
* \tparam ElemType The type of objects stored in the array right after
* ArrayType.
*
* \code{.cpp}
* // Example usage of the template to define a simple array wrapper
* class ArrayObj : public tvm::ffi::details::InplaceArrayBase<ArrayObj, Elem> {
* public:
* // Wrap EmplaceInit to initialize the elements
* template <typename Iterator>
* void Init(Iterator begin, Iterator end) {
* size_t num_elems = std::distance(begin, end);
* auto it = begin;
* this->size = 0;
* for (size_t i = 0; i < num_elems; ++i) {
* InplaceArrayBase::EmplaceInit(i, *it++);
* this->size++;
* }
* }
* }
*
* void test_function() {
* vector<Elem> fields;
* auto ptr = make_inplace_array_object<ArrayObj, Elem>(fields.size());
* ptr->Init(fields.begin(), fields.end());
*
* // Access the 0th element in the array.
* assert(ptr->operator[](0) == fields[0]);
* }
* \endcode
*/
template <typename ArrayType, typename ElemType>
class InplaceArrayBase {
public:
/*!
* \brief Access element at index
* \param idx The index of the element.
* \return Const reference to ElemType at the index.
*/
const ElemType& operator[](size_t idx) const {
size_t size = Self()->GetSize();
if (idx > size) {
TVM_FFI_THROW(IndexError) << "Index " << idx << " out of bounds " << size;
}
return *(reinterpret_cast<ElemType*>(AddressOf(idx)));
}

/*!
* \brief Access element at index
* \param idx The index of the element.
* \return Reference to ElemType at the index.
*/
ElemType& operator[](size_t idx) {
size_t size = Self()->GetSize();
if (idx > size) {
TVM_FFI_THROW(IndexError) << "Index " << idx << " out of bounds " << size;
}
return *(reinterpret_cast<ElemType*>(AddressOf(idx)));
}

/*!
* \brief Destroy the Inplace Array Base object
*/
~InplaceArrayBase() {
if constexpr (!(std::is_standard_layout_v<ElemType> && std::is_trivial_v<ElemType>)) {
size_t size = Self()->GetSize();
for (size_t i = 0; i < size; ++i) {
ElemType* fp = reinterpret_cast<ElemType*>(AddressOf(i));
fp->ElemType::~ElemType();
}
}
}

private:
InplaceArrayBase() = default;
friend ArrayType;

protected:
/*!
* \brief Construct a value in place with the arguments.
*
* \tparam Args Type parameters of the arguments.
* \param idx Index of the element.
* \param args Arguments to construct the new value.
*
* \note Please make sure ArrayType::GetSize returns 0 before first call of
* EmplaceInit, and increment GetSize by 1 each time EmplaceInit succeeds.
*/
template <typename... Args>
void EmplaceInit(size_t idx, Args&&... args) {
void* field_ptr = AddressOf(idx);
new (field_ptr) ElemType(std::forward<Args>(args)...);
}

/*!
* \brief Return the self object for the array.
*
* \return Pointer to ArrayType.
*/
inline ArrayType* Self() const {
return static_cast<ArrayType*>(const_cast<InplaceArrayBase*>(this));
}

/*!
* \brief Return the raw pointer to the element at idx.
*
* \param idx The index of the element.
* \return Raw pointer to the element.
*/
void* AddressOf(size_t idx) const {
static_assert(
alignof(ArrayType) % alignof(ElemType) == 0 && sizeof(ArrayType) % alignof(ElemType) == 0,
"The size and alignment of ArrayType should respect "
"ElemType's alignment.");

size_t kDataStart = sizeof(ArrayType);
ArrayType* self = Self();
char* data_start = reinterpret_cast<char*>(self) + kDataStart;
return data_start + idx * sizeof(ElemType);
}
};

/*!
* \brief iterator adapter that adapts TIter to return another type.
Expand Down
Loading