Skip to content

Commit b896ad8

Browse files
authored
[FFI][REFACTOR] Stablize container ABI and implementation (apache#18076)
1 parent b9a1c60 commit b896ad8

File tree

3 files changed

+166
-78
lines changed

3 files changed

+166
-78
lines changed

include/tvm/ffi/container/array.h

Lines changed: 56 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -42,8 +42,18 @@ namespace tvm {
4242
namespace ffi {
4343

4444
/*! \brief array node content in array */
45-
class ArrayObj : public Object, public details::InplaceArrayBase<ArrayObj, Any> {
45+
class ArrayObj : public Object, public details::InplaceArrayBase<ArrayObj, TVMFFIAny> {
4646
public:
47+
~ArrayObj() {
48+
Any* begin = MutableBegin();
49+
for (int64_t i = 0; i < size_; ++i) {
50+
(begin + i)->Any::~Any();
51+
}
52+
if (data_deleter_ != nullptr) {
53+
data_deleter_(data_);
54+
}
55+
}
56+
4757
/*! \return The size of the array */
4858
size_t size() const { return this->size_; }
4959

@@ -52,10 +62,22 @@ class ArrayObj : public Object, public details::InplaceArrayBase<ArrayObj, Any>
5262
* \param i The index
5363
* \return the i-th element.
5464
*/
55-
const Any at(int64_t i) const { return this->operator[](i); }
65+
const Any& at(int64_t i) const { return this->operator[](i); }
66+
67+
/*!
68+
* \brief Read i-th element from array.
69+
* \param i The index
70+
* \return the i-th element.
71+
*/
72+
const Any& operator[](int64_t i) const {
73+
if (i >= size_) {
74+
TVM_FFI_THROW(IndexError) << "Index " << i << " out of bounds " << size_;
75+
}
76+
return static_cast<Any*>(data_)[i];
77+
}
5678

5779
/*! \return begin constant iterator */
58-
const Any* begin() const { return static_cast<Any*>(InplaceArrayBase::AddressOf(0)); }
80+
const Any* begin() const { return static_cast<Any*>(data_); }
5981

6082
/*! \return end constant iterator */
6183
const Any* end() const { return begin() + size_; }
@@ -68,7 +90,12 @@ class ArrayObj : public Object, public details::InplaceArrayBase<ArrayObj, Any>
6890
* \param i The index
6991
* \param item The value to be set
7092
*/
71-
void SetItem(int64_t i, Any item) { this->operator[](i) = std::move(item); }
93+
void SetItem(int64_t i, Any item) {
94+
if (i >= size_) {
95+
TVM_FFI_THROW(IndexError) << "Index " << i << " out of bounds " << size_;
96+
}
97+
static_cast<Any*>(data_)[i] = std::move(item);
98+
}
7299

73100
/*!
74101
* \brief Constructs a container and copy from another
@@ -138,21 +165,31 @@ class ArrayObj : public Object, public details::InplaceArrayBase<ArrayObj, Any>
138165
size_t GetSize() const { return this->size_; }
139166

140167
/*! \return begin mutable iterator */
141-
Any* MutableBegin() const { return static_cast<Any*>(InplaceArrayBase::AddressOf(0)); }
168+
Any* MutableBegin() const { return static_cast<Any*>(this->data_); }
142169

143170
/*! \return end mutable iterator */
144171
Any* MutableEnd() const { return MutableBegin() + size_; }
145172

173+
/*!
174+
* \brief Emplace a new element at the back of the array
175+
* \param args The arguments to construct the new element
176+
*/
177+
template <typename... Args>
178+
void EmplaceInit(size_t idx, Args&&... args) {
179+
Any* itr = MutableBegin() + idx;
180+
new (itr) Any(std::forward<Args>(args)...);
181+
}
182+
146183
/*!
147184
* \brief Create an ArrayObj with the given capacity.
148185
* \param n Required capacity
149186
* \return Ref-counted ArrayObj requested
150187
*/
151188
static ObjectPtr<ArrayObj> Empty(int64_t n = kInitSize) {
152-
TVM_FFI_ICHECK_GE(n, 0);
153189
ObjectPtr<ArrayObj> p = make_inplace_array_object<ArrayObj, Any>(n);
154190
p->capacity_ = n;
155191
p->size_ = 0;
192+
p->data_ = p->AddressOf(0);
156193
return p;
157194
}
158195

@@ -235,11 +272,17 @@ class ArrayObj : public Object, public details::InplaceArrayBase<ArrayObj, Any>
235272
return this;
236273
}
237274

275+
/*! \brief Data pointer to the first element of the array */
276+
void* data_;
238277
/*! \brief Number of elements used */
239278
int64_t size_;
240-
241279
/*! \brief Number of elements allocated */
242280
int64_t capacity_;
281+
/*!
282+
* \brief Optional data deleter when data is allocated separately
283+
* and its deletion is not managed by ArrayObj::deleter_.
284+
*/
285+
void (*data_deleter_)(void*) = nullptr;
243286

244287
/*! \brief Initial size of ArrayObj */
245288
static constexpr int64_t kInitSize = 4;
@@ -472,6 +515,12 @@ class Array : public ObjectRef {
472515
p->EmplaceInit(p->size_++, item);
473516
}
474517

518+
template <typename... Args>
519+
void emplace_back(Args&&... args) {
520+
ArrayObj* p = CopyOnWrite(1);
521+
p->EmplaceInit(p->size_++, std::forward<Args>(args)...);
522+
}
523+
475524
/*!
476525
* \brief Insert an element into the given position
477526
* \param position An iterator pointing to the insertion point

0 commit comments

Comments
 (0)