Streamlined InputRecord / DataAllocator API Giulio Eulisse (CERN) WP4 - 24th Nov 2017 1
class via: 1https://github.com/AliceO2Group/AliceO2/blob/dev/Utilities/QC/Workflow/src/RootObjectProducerSpec.cxx 2 Improved API for DataAllocator (1) o2::framework::DataAllocator is the class which users must use to create output messages to be sent to the downstream DataProcessor s. It is now possible to create and serialise an instance of a TObject derived DataAllocator::make<T>(OutputSpec &spec, Args... args); e.g. in 1 : [](ProcessingContext &ctx) { auto h = ctx.allocator().make<TH1>(OutputSpec{”QC”, ”HISTO”}, ”h”, ”test”, 100, -10., 10.); }
made similar to the ROOT one: 3 Improved API for DataAllocator (2) Similarly the API to create PODs or Collection<POD> has been revamped and struct XYZ { float x,y,z; }; ... [](ProcessingContext &ctx) { // Create a XYZ instance which will be sent once lambda completes auto &a = ctx.allocator().make<XYZ>(OutputSpec{”TPC”, ”POINT”}); // Create a Collection<XYZ> with 1000 instances in it. auto &c = ctx.allocator().make<XYZ>(OutputSpec{”TPC”, ”POINT”}, 1000); }
processing function. The API to access the various parts of a record is now orthogonal as well. In the ROOT case it becomes: Notice that h will be a copy of the actual contents of the message buffer, due to the fact ROOT selializes objects. 4 Improved API for InputRecord (1) An o2::framework::InputRecord represents the inputs being passed to the {InputSpec{”histos”, ”QC”, ”HISTO”}} ... [](ProcessingContext &ctx) { auto h = ctx.inputs().get<TH1F>(”histos”); }
The same API can be used to extract a POD instance from the message as well: 5 Improved API for InputRecord (2) {InputSpec{”points”, ”QC”, ”HISTO”}} ... [](ProcessingContext &ctx) { XYZ &x = ctx.inputs().get<XYZ>(”points”); }
6 Improved API for InputRecord (3) By default, however, InputRecord::get still returns a o2::framework::DataRef i.e. the (header, payload) pointers. DataRefUtils::as<T> can then be used to extract stuff as well. {InputSpec{”points”, ”TPC”, ”POINTS”}} ... [](ProcessingContext &ctx) { auto ref = ctx.inputs().get(”points”); Collection<XYZ> c = DataRefUtils::as<XYZ>(ref); }
I already have an object… E.g. from Matthias last presentation 2 : becomes: 2https://github.com/AliceO2Group/AliceO2/blob/dev/Utilities/QC/Workflow/src/RootObjectProducerSpec.cxx 7 Use DataAllocator::adopt to surrender object ownership to the framework. auto dataobject = std::unique_ptr<TObject>(producer->produceData()); auto serialized = std::make_unique<TMessage>(kMESS_OBJECT); serialized->WriteObject(dataobject.get()); auto tgt = pc.allocator().newChunk(OutputSpec{”QC”, ”ROOTOBJECT”, 0, OutputSpec::QA}, serialized->BufferSize()); memcpy(tgt.data, serialized->Buffer(), tgt.size); pc.allocator().adopt(OutputSpec{”QC”, ”ROOTOBJECT”, 0, OutputSpec::QA}, producer->produceData());
Suggested future improvements whenever the object is actually owned by the DPL. At the moment I use a standard reference, but this has the drawback that if you are not careful you end up with a copy of the contents. 8 A non-owning pointer o2::ref<T> . Returned by ::make<T> , ::get<T> methods A static helper method o2::make<T> . To be used in place of DataAllocator::make<T> to hide the need to know about the allocator. Similarly o2::adopt<T> could be provided. Pass InputRecord directly . Assuming getting the inputs is very frequent, ctx.inputs().get(”something”) would becomes inputs.get(”somthing”) }
Recommend
More recommend