diff --git a/cpp/src/arrow/array/array_nested.cc b/cpp/src/arrow/array/array_nested.cc index b821451419a..b7f16860791 100644 --- a/cpp/src/arrow/array/array_nested.cc +++ b/cpp/src/arrow/array/array_nested.cc @@ -1076,20 +1076,25 @@ const ArrayVector& StructArray::fields() const { return boxed_fields_; } -const std::shared_ptr& StructArray::field(int i) const { +std::shared_ptr StructArray::field(int i) const { std::shared_ptr result = std::atomic_load(&boxed_fields_[i]); - if (!result) { - std::shared_ptr field_data; - if (data_->offset != 0 || data_->child_data[i]->length != data_->length) { - field_data = data_->child_data[i]->Slice(data_->offset, data_->length); - } else { - field_data = data_->child_data[i]; - } - result = MakeArray(field_data); - std::atomic_store(&boxed_fields_[i], std::move(result)); - return boxed_fields_[i]; + if (result) { + return result; } - return boxed_fields_[i]; + std::shared_ptr field_data; + if (data_->offset != 0 || data_->child_data[i]->length != data_->length) { + field_data = data_->child_data[i]->Slice(data_->offset, data_->length); + } else { + field_data = data_->child_data[i]; + } + result = MakeArray(field_data); + // Check if some other thread inserted the array in the meantime and return + // that in that case. + std::shared_ptr expected = nullptr; + if (!std::atomic_compare_exchange_strong(&boxed_fields_[i], &expected, result)) { + result = std::move(expected); + } + return result; } std::shared_ptr StructArray::GetFieldByName(const std::string& name) const { diff --git a/cpp/src/arrow/array/array_nested.h b/cpp/src/arrow/array/array_nested.h index f122f9378b5..2591fdaf414 100644 --- a/cpp/src/arrow/array/array_nested.h +++ b/cpp/src/arrow/array/array_nested.h @@ -692,7 +692,7 @@ class ARROW_EXPORT StructArray : public Array { // Return a shared pointer in case the requestor desires to share ownership // with this array. The returned array has its offset, length and null // count adjusted. - const std::shared_ptr& field(int pos) const; + std::shared_ptr field(int pos) const; const ArrayVector& fields() const;