17
17
18
18
#include " arrow/array/array_nested.h"
19
19
20
- #include < atomic>
21
20
#include < cstddef>
22
21
#include < cstdint>
23
22
#include < memory>
23
+ #include < mutex>
24
24
#include < string>
25
25
#include < utility>
26
26
#include < vector>
@@ -1004,10 +1004,18 @@ Result<std::shared_ptr<Array>> FixedSizeListArray::Flatten(
1004
1004
// ----------------------------------------------------------------------
1005
1005
// Struct
1006
1006
1007
+ struct StructArray ::Impl {
1008
+ std::mutex mutex;
1009
+ ArrayVector boxed_fields;
1010
+ };
1011
+
1012
+ StructArray::~StructArray () = default ;
1013
+
1007
1014
StructArray::StructArray (const std::shared_ptr<ArrayData>& data) {
1008
1015
ARROW_CHECK_EQ (data->type ->id (), Type::STRUCT);
1009
1016
SetData (data);
1010
- boxed_fields_.resize (data->child_data .size ());
1017
+ impl_ = std::make_unique<Impl>();
1018
+ impl_->boxed_fields .resize (data_->child_data .size ());
1011
1019
}
1012
1020
1013
1021
StructArray::StructArray (const std::shared_ptr<DataType>& type, int64_t length,
@@ -1016,10 +1024,12 @@ StructArray::StructArray(const std::shared_ptr<DataType>& type, int64_t length,
1016
1024
int64_t offset) {
1017
1025
ARROW_CHECK_EQ (type->id (), Type::STRUCT);
1018
1026
SetData (ArrayData::Make (type, length, {std::move (null_bitmap)}, null_count, offset));
1027
+ data_->child_data .reserve (children.size ());
1019
1028
for (const auto & child : children) {
1020
1029
data_->child_data .push_back (child->data ());
1021
1030
}
1022
- boxed_fields_.resize (children.size ());
1031
+ impl_ = std::make_unique<Impl>();
1032
+ impl_->boxed_fields .resize (data_->child_data .size ());
1023
1033
}
1024
1034
1025
1035
Result<std::shared_ptr<StructArray>> StructArray::Make (
@@ -1069,27 +1079,32 @@ const StructType* StructArray::struct_type() const {
1069
1079
return checked_cast<const StructType*>(data_->type .get ());
1070
1080
}
1071
1081
1082
+ std::shared_ptr<Array> StructArray::MakeBoxedField (int i) const {
1083
+ std::shared_ptr<ArrayData> field_data;
1084
+ if (data_->offset != 0 || data_->child_data [i]->length != data_->length ) {
1085
+ field_data = data_->child_data [i]->Slice (data_->offset , data_->length );
1086
+ } else {
1087
+ field_data = data_->child_data [i];
1088
+ }
1089
+ return MakeArray (field_data);
1090
+ }
1091
+
1072
1092
const ArrayVector& StructArray::fields () const {
1093
+ std::lock_guard lock (impl_->mutex );
1073
1094
for (int i = 0 ; i < num_fields (); ++i) {
1074
- (void )field (i);
1095
+ if (impl_->boxed_fields [i] == nullptr ) {
1096
+ impl_->boxed_fields [i] = MakeBoxedField (i);
1097
+ }
1075
1098
}
1076
- return boxed_fields_ ;
1099
+ return impl_-> boxed_fields ;
1077
1100
}
1078
1101
1079
1102
const std::shared_ptr<Array>& StructArray::field (int i) const {
1080
- std::shared_ptr<Array> result = std::atomic_load (&boxed_fields_[i]);
1081
- if (!result) {
1082
- std::shared_ptr<ArrayData> field_data;
1083
- if (data_->offset != 0 || data_->child_data [i]->length != data_->length ) {
1084
- field_data = data_->child_data [i]->Slice (data_->offset , data_->length );
1085
- } else {
1086
- field_data = data_->child_data [i];
1087
- }
1088
- result = MakeArray (field_data);
1089
- std::atomic_store (&boxed_fields_[i], std::move (result));
1090
- return boxed_fields_[i];
1103
+ std::lock_guard lock (impl_->mutex );
1104
+ if (impl_->boxed_fields [i] == nullptr ) {
1105
+ impl_->boxed_fields [i] = MakeBoxedField (i);
1091
1106
}
1092
- return boxed_fields_ [i];
1107
+ return impl_-> boxed_fields [i];
1093
1108
}
1094
1109
1095
1110
std::shared_ptr<Array> StructArray::GetFieldByName (const std::string& name) const {
@@ -1177,14 +1192,24 @@ Result<std::shared_ptr<Array>> StructArray::GetFlattenedField(int index,
1177
1192
// ----------------------------------------------------------------------
1178
1193
// UnionArray
1179
1194
1195
+ struct UnionArray ::Impl {
1196
+ std::mutex mutex;
1197
+ ArrayVector boxed_fields;
1198
+ };
1199
+
1200
+ UnionArray::UnionArray () = default ;
1201
+ UnionArray::~UnionArray () = default ;
1202
+
1180
1203
void UnionArray::SetData (std::shared_ptr<ArrayData> data) {
1181
1204
this ->Array ::SetData (std::move (data));
1182
1205
1183
1206
union_type_ = checked_cast<const UnionType*>(data_->type .get ());
1184
1207
1185
1208
ARROW_CHECK_GE (data_->buffers .size (), 2 );
1186
1209
raw_type_codes_ = data->GetValuesSafe <int8_t >(1 );
1187
- boxed_fields_.resize (data_->child_data .size ());
1210
+
1211
+ impl_ = std::make_unique<Impl>();
1212
+ impl_->boxed_fields .resize (data_->child_data .size ());
1188
1213
}
1189
1214
1190
1215
void SparseUnionArray::SetData (std::shared_ptr<ArrayData> data) {
@@ -1198,16 +1223,16 @@ void SparseUnionArray::SetData(std::shared_ptr<ArrayData> data) {
1198
1223
1199
1224
void DenseUnionArray::SetData (const std::shared_ptr<ArrayData>& data) {
1200
1225
this ->UnionArray ::SetData (data);
1201
-
1202
1226
ARROW_CHECK_EQ (data_->type ->id (), Type::DENSE_UNION);
1203
1227
ARROW_CHECK_EQ (data_->buffers .size (), 3 );
1204
1228
1205
1229
// No validity bitmap
1206
1230
ARROW_CHECK_EQ (data_->buffers [0 ], nullptr );
1207
-
1208
1231
raw_value_offsets_ = data->GetValuesSafe <int32_t >(2 );
1209
1232
}
1210
1233
1234
+ SparseUnionArray::~SparseUnionArray () = default ;
1235
+
1211
1236
SparseUnionArray::SparseUnionArray (std::shared_ptr<ArrayData> data) {
1212
1237
SetData (std::move (data));
1213
1238
}
@@ -1261,6 +1286,8 @@ Result<std::shared_ptr<Array>> SparseUnionArray::GetFlattenedField(
1261
1286
return MakeArray (child_data);
1262
1287
}
1263
1288
1289
+ DenseUnionArray::~DenseUnionArray () = default ;
1290
+
1264
1291
DenseUnionArray::DenseUnionArray (const std::shared_ptr<ArrayData>& data) {
1265
1292
SetData (data);
1266
1293
}
@@ -1352,26 +1379,29 @@ Result<std::shared_ptr<Array>> SparseUnionArray::Make(
1352
1379
return std::make_shared<SparseUnionArray>(std::move (internal_data));
1353
1380
}
1354
1381
1382
+ std::shared_ptr<Array> UnionArray::MakeBoxedField (int i) const {
1383
+ std::shared_ptr<ArrayData> child_data = data_->child_data [i]->Copy ();
1384
+ if (mode () == UnionMode::SPARSE) {
1385
+ // Sparse union: need to adjust child if union is sliced
1386
+ // (for dense unions, the need to lookup through the offsets
1387
+ // makes this unnecessary)
1388
+ if (data_->offset != 0 || child_data->length > data_->length ) {
1389
+ child_data = child_data->Slice (data_->offset , data_->length );
1390
+ }
1391
+ }
1392
+ return MakeArray (child_data);
1393
+ }
1394
+
1355
1395
std::shared_ptr<Array> UnionArray::field (int i) const {
1356
- if (i < 0 ||
1357
- static_cast <decltype (boxed_fields_)::size_type>(i) >= boxed_fields_.size ()) {
1396
+ if (i < 0 || i >= num_fields ()) {
1358
1397
return nullptr ;
1359
1398
}
1360
- std::shared_ptr<Array> result = std::atomic_load (&boxed_fields_[i]);
1361
- if (!result) {
1362
- std::shared_ptr<ArrayData> child_data = data_->child_data [i]->Copy ();
1363
- if (mode () == UnionMode::SPARSE) {
1364
- // Sparse union: need to adjust child if union is sliced
1365
- // (for dense unions, the need to lookup through the offsets
1366
- // makes this unnecessary)
1367
- if (data_->offset != 0 || child_data->length > data_->length ) {
1368
- child_data = child_data->Slice (data_->offset , data_->length );
1369
- }
1370
- }
1371
- result = MakeArray (child_data);
1372
- std::atomic_store (&boxed_fields_[i], result);
1399
+
1400
+ std::lock_guard lock (impl_->mutex );
1401
+ if (impl_->boxed_fields [i] == nullptr ) {
1402
+ impl_->boxed_fields [i] = MakeBoxedField (i);
1373
1403
}
1374
- return result ;
1404
+ return impl_-> boxed_fields [i] ;
1375
1405
}
1376
1406
1377
1407
} // namespace arrow
0 commit comments