Repository: apache/arrow
File: cpp/src/arrow/array/array_nested.cc (C++)

Code before:
  return checked_cast<const StructType*>(data_->type.get());
}

const ArrayVector& StructArray::fields() const {
  for (int i = 0; i < num_fields(); ++i) {
    (void)field(i);
  }
  return boxed_fields_;
}

std::shared_ptr<Array> StructArray::field(int i) const {
  std::shared_ptr<Array> result = std::atomic_load(&boxed_fields_[i]);
  if (result) {
    return result;
  }
  std::shared_ptr<ArrayData> 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<Array> expected = nullptr;
  if (!std::atomic_compare_exchange_strong_explicit(&boxed_fields_[i], &expected, result,
                                                    std::memory_order_release,
                                                    std::memory_order_acquire)) {
    result = std::move(expected);
  }
  return result;
}

std::shared_ptr<Array> StructArray::GetFieldByName(const std::string& name) const {
  int i = struct_type()->GetFieldIndex(name);
  return i == -1 ? nullptr : field(i);
}

Status StructArray::CanReferenceFieldByName(const std::string& name) const {
  if (GetFieldByName(name) == nullptr) {
    return Status::Invalid("Field named '", name,
                           "' not found or not unique in the struct.");
  }
  return Status::OK();
}

Status StructArray::CanReferenceFieldsByNames(
    const std::vector<std::string>& names) const {
  for (const auto& name : names) {
    ARROW_RETURN_NOT_OK(CanReferenceFieldByName(name));
  }

Review comment (suggestion):
I would feel more confident using simply `std::atomic_compare_exchange_strong`.

Code after:
  return checked_cast<const StructType*>(data_->type.get());
}

const ArrayVector& StructArray::fields() const {
  for (int i = 0; i < num_fields(); ++i) {
    (void)field(i);
  }
  return boxed_fields_;
}

std::shared_ptr<Array> StructArray::field(int i) const {
  std::shared_ptr<Array> result = std::atomic_load(&boxed_fields_[i]);
  if (result) {
    return result;
  }
  std::shared_ptr<ArrayData> 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<Array> expected = nullptr;
  if (!std::atomic_compare_exchange_strong(&boxed_fields_[i], &expected, result)) {
    result = std::move(expected);
  }
  return result;
}

std::shared_ptr<Array> StructArray::GetFieldByName(const std::string& name) const {
  int i = struct_type()->GetFieldIndex(name);
  return i == -1 ? nullptr : field(i);
}

Status StructArray::CanReferenceFieldByName(const std::string& name) const {
  if (GetFieldByName(name) == nullptr) {
    return Status::Invalid("Field named '", name,
                           "' not found or not unique in the struct.");
  }
  return Status::OK();
}

Status StructArray::CanReferenceFieldsByNames(
    const std::vector<std::string>& names) const {
  for (const auto& name : names) {
    ARROW_RETURN_NOT_OK(CanReferenceFieldByName(name));
  }
  return Status::OK();
}