Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
RFieldSoA.hxx
Go to the documentation of this file.
1/// \file ROOT/RField/RFieldSoA.hxx
2/// \author Jakob Blomer <jblomer@cern.ch>
3/// \date 2026-03-03
4
5/*************************************************************************
6 * Copyright (C) 1995-2026, Rene Brun and Fons Rademakers. *
7 * All rights reserved. *
8 * *
9 * For the licensing terms see $ROOTSYS/LICENSE. *
10 * For the list of contributors see $ROOTSYS/README/CREDITS. *
11 *************************************************************************/
12
13#ifndef ROOT_RField_SoA
14#define ROOT_RField_SoA
15
16#ifndef ROOT_RField
17#error "Please include RField.hxx!"
18#endif
19
20#include <ROOT/RFieldBase.hxx>
21#include <ROOT/RNTupleTypes.hxx>
22
23#include <cstddef>
24#include <functional>
25#include <memory>
26#include <mutex>
27#include <string_view>
28#include <typeinfo>
29#include <vector>
30
31class TClass;
32
33namespace ROOT {
34
35/// The SoA field provides I/O for an in-memory SoA layout linked to an on-disk collection of the underlying record.
36/// As a concrete example, for an underlying record type
37/// \code{.cpp}
38/// struct PointRecord {
39/// float px, py;
40/// };
41/// \endcode
42/// a corresponding SoA layout will look like
43/// \code{.cpp}
44/// struct PointSoA {
45/// ROOT::RVec<float> px;
46/// ROOT::RVec<float> py;
47/// };
48/// \endcode
49///
50/// The SoA type has to be marked in the dictionary with the rntupleSoARecord attribute.
51///
52/// Since the on-disk representation is a collection of record type, the class version and checksum of the SoA type
53/// itself is ignored.
54class RSoAField : public RRuleField {
55 class RSoADeleter : public RDeleter {
56 private:
58
59 public:
60 explicit RSoADeleter(TClass *cl);
61 void operator()(void *objPtr, bool dtorOnly) final;
62 };
63
64 // A rule of the SoA type itself or one of its nested SoA types or base classes, togther with the offset
65 // of the nested object in the SoA type.
66 struct RRule {
67 const TSchemaRule *fRule = nullptr;
68 std::size_t fOffset = 0;
69 };
70
71 /// Direct access to the member fields of the underlying record. In case of a nested SoA type, this vector
72 /// contains the contents of the inner fRecordMemberFields, too. Effectively, this record will contain all the
73 /// fields of the underlying record type that correspond to terminal RVec members in a nested SoA type.
74 /// Pointers in this vector point into the field hierarchy owned by fSubfields[0].
75 std::vector<RFieldBase *> fRecordMemberFields;
76 /// The offset of the RVec members in the SoA type in the same order as fRecordMemberFields.
77 std::vector<std::size_t> fSoAMemberOffsets;
78 ///< A deleter returned by each record member's GetDeleter()
79 std::vector<std::unique_ptr<RDeleter>> fRecordMemberDeleters;
81
82 /// Contains the I/O customization rules for fClass and all nested SoA classes and base classes,
83 /// and the relative offset at which the rule needs to be applied.
84 std::vector<RRule> fRules;
85
86 /// For reading and writing, the RVecs of the SoA class do not have a dedicated field. The in-memory RVecs of the
87 /// SoA object are used directly with the subfields of the underlying record type. For splitting a SoA class object
88 /// (SplitValue()), however, we need actual RRVecFields so that we can recursively split the in-memory SoA value.
89 /// The split fields are created only when SplitField() is called.
90 /// In general, the number of split fields is different from the number of record member fields because there is
91 /// one split field for every _direct_ member of the SoA class. Because nested SoA structs can have transient
92 /// members, we can also not reuse fSoAMemberOffsets but we need to store the data member offsets.
93 mutable std::unique_ptr<std::vector<std::unique_ptr<ROOT::RFieldBase>>> fSplitFields;
94 mutable std::unique_ptr<std::vector<std::size_t>> fSplitOffsets;
95 mutable std::unique_ptr<std::mutex> fLockSplitFields; ///< protects the fSplitFields member.
96
97 RSoAField(std::string_view fieldName, const RSoAField &source); ///< Used by CloneImpl
98 RSoAField(std::string_view fieldName, TClass *clSoA);
99
100 /// Called during construction, picks up the (nested) member fields of the underlying record type(s) and its
101 /// base classes. Also fills fRules.
103 /// For a nested SoA struct (either as a member of as a base class), use their fRecordMemberFields in this class,
104 /// i.e. "unroll" the vectors in the nested SoA struct into the SoA base class.
105 void GraftNestedMemberFields(const RSoAField &nestedSoA, std::size_t offsetInParent,
106 const std::function<RFieldBase *(const std::string &)> &fnRecordFieldFinder);
107
108 void ReconstructSplitFields() const;
109
110protected:
111 std::unique_ptr<RFieldBase> CloneImpl(std::string_view newName) const final;
112
114 void GenerateColumns() final;
115 void GenerateColumns(const ROOT::RNTupleDescriptor &desc) final;
116
117 void ConstructValue(void *where) const final;
118 std::unique_ptr<RDeleter> GetDeleter() const final { return std::make_unique<RSoADeleter>(fClass); }
119
120 std::size_t AppendImpl(const void *from) final;
121 void ReadGlobalImpl(ROOT::NTupleSize_t globalIndex, void *to) final;
122
123 void CommitClusterImpl() final { fNWritten = 0; }
124
125 std::unique_ptr<RFieldBase> BeforeConnectPageSource(ROOT::Internal::RPageSource &pageSource) final;
126 void ReconcileOnDiskField(const RNTupleDescriptor &desc) final;
127
128public:
129 RSoAField(std::string_view fieldName, std::string_view className);
130 RSoAField(RSoAField &&other) = default;
131 RSoAField &operator=(RSoAField &&other) = default;
132 ~RSoAField() override = default;
133
134 std::vector<RValue> SplitValue(const RValue &value) const final;
135 size_t GetValueSize() const final;
136 size_t GetAlignment() const final;
137 std::uint32_t GetTypeVersion() const final;
138 std::uint32_t GetTypeChecksum() const final;
139 /// For polymorphic classes (that declare or inherit at least one virtual method), return the expected dynamic type
140 /// of any user object. If the class is not polymorphic, return nullptr.
141 /// TODO(jblomer): use information in unique pointer field
142 const std::type_info *GetPolymorphicTypeInfo() const;
143 void AcceptVisitor(ROOT::Detail::RFieldVisitor &visitor) const final;
144
145 TClass *GetSoAClass() const { return fClass; }
146};
147
148} // namespace ROOT
149
150#endif // ROOT_RField_SoA
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void value
Abstract base class for classes implementing the visitor design pattern.
The in-memory representation of a 32bit or 64bit on-disk index column.
Abstract interface to read data from an ntuple.
The list of column representations a field can have.
A functor to release the memory acquired by CreateValue() (memory and constructor).
Points to an object with RNTuple I/O support and keeps a pointer to the corresponding field.
A field translates read and write calls from/to underlying columns to/from tree values.
The on-storage metadata of an RNTuple.
Base class for fields that are subject to I/O customization rules. Used by the class field and the So...
Definition RField.hxx:135
TClass * fClass
Set by derived class to the TClass instance representing the current in-memory layout.
Definition RField.hxx:148
void operator()(void *objPtr, bool dtorOnly) final
The SoA field provides I/O for an in-memory SoA layout linked to an on-disk collection of the underly...
Definition RFieldSoA.hxx:54
std::unique_ptr< std::mutex > fLockSplitFields
protects the fSplitFields member.
Definition RFieldSoA.hxx:95
void ConstructValue(void *where) const final
Constructs value in a given location of size at least GetValueSize(). Called by the base class' Creat...
TClass * GetSoAClass() const
const std::type_info * GetPolymorphicTypeInfo() const
For polymorphic classes (that declare or inherit at least one virtual method), return the expected dy...
std::vector< RFieldBase * > fRecordMemberFields
Direct access to the member fields of the underlying record.
Definition RFieldSoA.hxx:75
size_t GetValueSize() const final
What sizeof(T) for this type returns.
std::vector< std::unique_ptr< RDeleter > > fRecordMemberDeleters
Definition RFieldSoA.hxx:79
std::unique_ptr< RDeleter > GetDeleter() const final
std::unique_ptr< RFieldBase > BeforeConnectPageSource(ROOT::Internal::RPageSource &pageSource) final
Called by ConnectPageSource() before connecting; derived classes may override this as appropriate,...
void ReconcileOnDiskField(const RNTupleDescriptor &desc) final
For non-artificial fields, check compatibility of the in-memory field and the on-disk field.
void CollectRecordMemberFields()
Called during construction, picks up the (nested) member fields of the underlying record type(s) and ...
std::unique_ptr< RFieldBase > CloneImpl(std::string_view newName) const final
Called by Clone(), which additionally copies the on-disk ID.
void ReconstructSplitFields() const
ROOT::Internal::RColumnIndex fNWritten
Definition RFieldSoA.hxx:80
std::vector< std::size_t > fSoAMemberOffsets
The offset of the RVec members in the SoA type in the same order as fRecordMemberFields.
Definition RFieldSoA.hxx:77
RSoAField(std::string_view fieldName, const RSoAField &source)
Used by CloneImpl.
std::vector< RValue > SplitValue(const RValue &value) const final
Creates the list of direct child values given an existing value for this field.
~RSoAField() override=default
std::unique_ptr< std::vector< std::size_t > > fSplitOffsets
Definition RFieldSoA.hxx:94
std::vector< RRule > fRules
Contains the I/O customization rules for fClass and all nested SoA classes and base classes,...
Definition RFieldSoA.hxx:84
std::uint32_t GetTypeVersion() const final
Indicates an evolution of the C++ type itself.
void GenerateColumns() final
Implementations in derived classes should create the backing columns corresponding to the field type ...
RSoAField & operator=(RSoAField &&other)=default
size_t GetAlignment() const final
What alignof(T) for this type returns.
std::size_t AppendImpl(const void *from) final
Operations on values of complex types, e.g.
const RColumnRepresentations & GetColumnRepresentations() const final
Implementations in derived classes should return a static RColumnRepresentations object.
std::unique_ptr< std::vector< std::unique_ptr< ROOT::RFieldBase > > > fSplitFields
For reading and writing, the RVecs of the SoA class do not have a dedicated field.
Definition RFieldSoA.hxx:93
void AcceptVisitor(ROOT::Detail::RFieldVisitor &visitor) const final
std::uint32_t GetTypeChecksum() const final
Return the current TClass reported checksum of this class. Only valid if kTraitTypeChecksum is set.
void ReadGlobalImpl(ROOT::NTupleSize_t globalIndex, void *to) final
RSoAField(RSoAField &&other)=default
void GraftNestedMemberFields(const RSoAField &nestedSoA, std::size_t offsetInParent, const std::function< RFieldBase *(const std::string &)> &fnRecordFieldFinder)
For a nested SoA struct (either as a member of as a base class), use their fRecordMemberFields in thi...
void CommitClusterImpl() final
TClass instances represent classes, structs and namespaces in the ROOT type system.
Definition TClass.h:84
std::uint64_t NTupleSize_t
Integer type long enough to hold the maximum number of entries in a column.
const TSchemaRule * fRule
Definition RFieldSoA.hxx:67