Project
Loading...
Searching...
No Matches
FlatObject.h
Go to the documentation of this file.
1// Copyright 2019-2020 CERN and copyright holders of ALICE O2.
2// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders.
3// All rights not expressly granted are reserved.
4//
5// This software is distributed under the terms of the GNU General Public
6// License v3 (GPL Version 3), copied verbatim in the file "COPYING".
7//
8// In applying this license CERN does not waive the privileges and immunities
9// granted to it by virtue of its status as an Intergovernmental Organization
10// or submit itself to any jurisdiction.
11
16
17#ifndef ALICEOW_GPUCOMMON_TPCFASTTRANSFORMATION_FLATOBJECT_H
18#define ALICEOW_GPUCOMMON_TPCFASTTRANSFORMATION_FLATOBJECT_H
19
20#if !defined(GPUCA_GPUCODE_DEVICE)
21#include <cstddef>
22#include <memory>
23#include <cstring>
24#include <cassert>
25#endif
26
27#include "GPUCommonDef.h"
28#include "GPUCommonRtypes.h"
29#include "GPUCommonLogger.h"
30
31// #define GPUCA_GPUCODE // uncomment to test "GPU" mode
32
33namespace o2
34{
35namespace gpu
36{
79//
117
119{
120 public:
122
124#ifndef GPUCA_GPUCODE
125 FlatObject() = default; // No object derrived from FlatObject should be created on the GPU
126 ~FlatObject();
127 FlatObject(const FlatObject&) = delete;
128 FlatObject& operator=(const FlatObject&) = delete;
129#else
130 FlatObject() = delete;
131#endif
132
133#ifndef GPUCA_GPUCODE // code invisible on GPU
134 template <typename T>
135 T* resizeArray(T*& ptr, int32_t oldSize, int32_t newSize, T* newPtr = nullptr)
136 {
137 // Resize array pointed by ptr. T must be a POD class.
138 // If the non-null newPtr is provided, use it instead of allocating a new one.
139 // In this case it is up to the user to ensure that it has at least newSize slots allocated.
140 // Return original array pointer, so that the user can manage previously allocate memory
141 if (oldSize < 0) {
142 oldSize = 0;
143 }
144 if (newSize > 0) {
145 if (!newPtr) {
146 newPtr = new T[newSize];
147 }
148 int32_t mcp = std::min(newSize, oldSize);
149 if (mcp) {
150 assert(ptr);
151 std::memmove(newPtr, ptr, mcp * sizeof(T));
152 }
153 if (newSize > oldSize) {
154 std::memset(newPtr + mcp, 0, (newSize - oldSize) * sizeof(T));
155 }
156 }
157 T* oldPtr = ptr;
158 ptr = newPtr;
159 return oldPtr;
160 }
161
162 template <typename T>
163 T** resizeArray(T**& ptr, int32_t oldSize, int32_t newSize, T** newPtr = nullptr)
164 {
165 // Resize array of pointers pointed by ptr.
166 // If the non-null newPtr is provided, use it instead of allocating a new one.
167 // In this case it is up to the user to ensure that it has at least newSize slots allocated.
168 // Return original array pointer, so that the user can manage previously allocate memory
169 if (oldSize < 0) {
170 oldSize = 0;
171 }
172 if (newSize > 0) {
173 if (!newPtr) {
174 newPtr = new T*[newSize];
175 }
176 int32_t mcp = std::min(newSize, oldSize);
177 std::memmove(newPtr, ptr, mcp * sizeof(T*));
178 if (newSize > oldSize) {
179 std::memset(newPtr + mcp, 0, (newSize - oldSize) * sizeof(T*));
180 }
181 }
182 T** oldPtr = ptr;
183 ptr = newPtr;
184 return oldPtr;
185 }
186#endif
187
188 protected:
190
192 static constexpr size_t getClassAlignmentBytes() { return 8; }
193
195 static constexpr size_t getBufferAlignmentBytes() { return 8; }
196
198
200 void startConstruction();
201
205 void finishConstruction(int32_t flatBufferSize);
206
211#ifndef GPUCA_GPUCODE
212 void cloneFromObject(const FlatObject& obj, char* newFlatBufferPtr);
213#endif // !GPUCA_GPUCODE
214
216
217 // Returns an unique pointer to the internal buffer with all the rights. Makes the internal container variable empty.
219
222#ifndef GPUCA_GPUCODE
223 void moveBufferTo(char* newBufferPtr);
224#endif // !GPUCA_GPUCODE
225
227
232 void setActualBufferAddress(char* actualFlatBufferPtr);
233
245 void setFutureBufferAddress(char* futureFlatBufferPtr);
246
248
249 public:
251 void destroy();
252
254 GPUdi() size_t getFlatBufferSize() const { return mFlatBufferSize; }
255
257 GPUdi() const char* getFlatBufferPtr() const { return mFlatBufferPtr; }
258
261
263 bool isBufferInternal() const { return ((mFlatBufferPtr != nullptr) && (mFlatBufferPtr == mFlatBufferContainer)); }
264
265 // Adopt an external pointer as internal buffer
266 void adoptInternalBuffer(char* buf);
267
268 // Hard reset of internal pointer to nullptr without deleting (needed copying an object without releasing)
270
272
273 public:
275 static constexpr size_t alignSize(size_t sizeBytes, size_t alignmentBytes)
276 {
277 auto res = sizeBytes % alignmentBytes;
278 return res ? sizeBytes + (alignmentBytes - res) : sizeBytes;
279 }
280
282 template <class T>
283 static T* relocatePointer(const char* oldBase, char* newBase, const T* ptr)
284 {
285 return (ptr != nullptr) ? reinterpret_cast<T*>(newBase + (reinterpret_cast<const char*>(ptr) - oldBase)) : nullptr;
286 }
287
288#if !defined(GPUCA_GPUCODE) && !defined(GPUCA_STANDALONE) // code invisible on GPU
289
291 template <class T, class TFile>
292 static int32_t writeToFile(T& obj, TFile& outf, const char* name);
293
295 template <class T, class TFile>
296 static T* readFromFile(TFile& inpf, const char* name);
297#endif
298
299#if !defined(GPUCA_GPUCODE) // code invisible on GPU
300
302 template <class T>
303 static std::string stressTest(T& obj);
304
306 void printC() const;
307
308#endif
309
310 protected:
312
314 enum ConstructionState : uint32_t {
317 InProgress = 0x2
318 };
319
320 int32_t mFlatBufferSize = 0;
322 char* mFlatBufferContainer = nullptr; //[mFlatBufferSize] Optional container for the flat buffer
323 char* mFlatBufferPtr = nullptr;
324
326};
327
334{
335 public:
336 int32_t mFlatBufferSize = 0;
337 static constexpr size_t getClassAlignmentBytes() { return 8; }
338 static constexpr size_t getBufferAlignmentBytes() { return 8; }
339 GPUdi() size_t getFlatBufferSize() const { return mFlatBufferSize; }
340};
341
347
348#ifndef GPUCA_GPUCODE // code invisible on GPU
350{
351 destroy();
352}
353
360
369
370inline void FlatObject::finishConstruction(int32_t flatBufferSize)
371{
374
376
377 mFlatBufferSize = flatBufferSize;
379
380 memset((void*)mFlatBufferPtr, 0, mFlatBufferSize); // just to avoid random behavior in case of bugs
381
382 mConstructionMask = (uint32_t)ConstructionState::Constructed; // clear other possible construction flags
383}
384
385inline void FlatObject::cloneFromObject(const FlatObject& obj, char* newFlatBufferPtr)
386{
390 // that we want to relocate the obj to external buffer)
391
392 assert(obj.isConstructed());
393
394 // providing *this with internal buffer as obj makes sens only if we want to conver it to object with PROVIDED external buffer
395 assert(!(!newFlatBufferPtr && obj.mFlatBufferPtr == mFlatBufferPtr && obj.isBufferInternal()));
396
397 char* oldPtr = resizeArray(mFlatBufferPtr, mFlatBufferSize, obj.mFlatBufferSize, newFlatBufferPtr);
398
399 if (isBufferInternal()) {
400 delete[] oldPtr; // delete old buffer if owned
401 }
403 mFlatBufferContainer = newFlatBufferPtr ? nullptr : mFlatBufferPtr; // external buffer is not provided, make object to own the buffer
404 std::memcpy(mFlatBufferPtr, obj.mFlatBufferPtr, obj.mFlatBufferSize);
406}
407
408inline void FlatObject::moveBufferTo(char* newFlatBufferPtr)
409{
411 if (newFlatBufferPtr == mFlatBufferContainer) {
412 return;
413 }
415 delete[] mFlatBufferContainer;
416 mFlatBufferContainer = nullptr;
417 if (!newFlatBufferPtr) { // resizeArray has created own array
419 }
420}
421
422template <class T>
423inline std::string FlatObject::stressTest(T& obj)
424{
428 std::string err;
429
430 if (!obj.isConstructed()) {
431 return "tested object is not constructed!";
432 }
433
434 T tst;
435 tst.cloneFromObject(obj, nullptr);
436 if (!tst.isConstructed() || !tst.isBufferInternal()) {
437 return "error at cloneFromObject()!";
438 }
439
440 obj.destroy();
441
442 char* buf0 = tst.releaseInternalBuffer();
443 char* buf1 = new char[tst.getFlatBufferSize()];
444 char* buf2 = new char[tst.getFlatBufferSize()];
445 std::memcpy(buf1, tst.getFlatBufferPtr(), tst.getFlatBufferSize());
446 tst.setActualBufferAddress(buf1);
447 delete[] buf0;
448
449 tst.setFutureBufferAddress(buf2);
450 std::memcpy(buf2, buf1, tst.getFlatBufferSize());
451 delete[] buf1;
452
453 if (tst.isBufferInternal()) {
454 return err = "error, buffer should be external!";
455 }
456
457 tst.adoptInternalBuffer(buf2);
458 if (!tst.isBufferInternal()) {
459 return err = "error, buffer should be internal!";
460 }
461
462 obj.cloneFromObject(tst, nullptr);
463 if (!obj.isBufferInternal()) {
464 return err = "error, buffer should be internal!";
465 }
466
467 return err;
468}
469
470inline void FlatObject::printC() const
471{
473 bool lfdone = false;
474 for (int32_t i = 0; i < mFlatBufferSize; i++) {
475 uint8_t v = mFlatBufferPtr[i];
476 lfdone = false;
477 printf("0x%02x ", v);
478 if (i && ((i + 1) % 20) == 0) {
479 printf("\n");
480 lfdone = true;
481 }
482 }
483 if (!lfdone) {
484 printf("\n");
485 }
486}
487
488#endif // GPUCA_GPUCODE
489
490#if !defined(GPUCA_GPUCODE) && !defined(GPUCA_STANDALONE) // code invisible on GPU
491template <class T, class TFile>
492inline int32_t FlatObject::writeToFile(T& obj, TFile& outf, const char* name)
493{
495 assert(obj.isConstructed());
496
497 if (outf.IsZombie()) {
498 LOG(error) << "Failed to write to file " << outf.GetName();
499 return -1;
500 }
501
502 bool isBufferExternal = !obj.isBufferInternal();
503 if (isBufferExternal) {
504 obj.adoptInternalBuffer(obj.mFlatBufferPtr);
505 }
506 outf.WriteObjectAny(&obj, T::Class(), name);
507 if (isBufferExternal) {
508 obj.clearInternalBufferPtr();
509 }
510 return 0;
511}
512
513template <class T, class TFile>
514inline T* FlatObject::readFromFile(TFile& inpf, const char* name)
515{
517
518 if (inpf.IsZombie()) {
519 LOG(error) << "Failed to read from file " << inpf.GetName();
520 return nullptr;
521 }
522 T* pobj = reinterpret_cast<T*>(inpf.GetObjectChecked(name, T::Class()));
523 if (!pobj) {
524 LOG(error) << "Failed to load " << name << " from " << inpf.GetName();
525 return nullptr;
526 }
527 if (pobj->mFlatBufferSize > 0 && pobj->mFlatBufferContainer == nullptr) {
528 LOG(error) << "Failed to load " << name << " from " << inpf.GetName() << ": empty flat buffer container";
529 return nullptr;
530 }
531 pobj->setActualBufferAddress(pobj->mFlatBufferContainer);
532 return pobj;
533}
534#endif // GPUCA_GPUCODE || GPUCA_STANDALONE
535
536#ifndef GPUCA_GPUCODE_DEVICE
537
539{
540 // returns an pointer to the internal buffer. Makes the internal container variable empty.
541 char* contPtr = mFlatBufferContainer;
542 mFlatBufferContainer = nullptr;
543 return contPtr;
544}
545
547{
548 // buf becomes the new internal buffer, after it was already set as new setActualBufferAddress
549 assert((mFlatBufferPtr == buf));
551}
552
554{
555 // we just release the internal buffer ressetting it to nullptr
556 mFlatBufferContainer = nullptr;
557}
558
559inline void FlatObject::setActualBufferAddress(char* actualFlatBufferPtr)
560{
565
566 mFlatBufferPtr = actualFlatBufferPtr;
567}
568
569inline void FlatObject::setFutureBufferAddress(char* futureFlatBufferPtr)
570{
575
576 assert(!isBufferInternal());
577 mFlatBufferPtr = futureFlatBufferPtr;
578#ifndef GPUCA_GPUCODE // code invisible on GPU
579 delete[] mFlatBufferContainer; // for a case..
580#endif // !GPUCA_GPUCODE
581 mFlatBufferContainer = nullptr;
582}
583
584#endif // GPUCA_GPUCODE_DEVICE
585
586} // namespace gpu
587} // namespace o2
588
589#endif
int32_t i
uint32_t res
Definition RawData.h:0
TBranch * ptr
char * releaseInternalBuffer()
_____________ Methods for making the data buffer external __________________________
Definition FlatObject.h:538
void setFutureBufferAddress(char *futureFlatBufferPtr)
Definition FlatObject.h:569
uint32_t mConstructionMask
mask for constructed object members, first two bytes are used by this class
Definition FlatObject.h:321
int32_t mFlatBufferSize
size of the flat buffer
Definition FlatObject.h:320
FlatObject & operator=(const FlatObject &)=delete
void printC() const
Print the content of the flat buffer.
Definition FlatObject.h:470
void adoptInternalBuffer(char *buf)
Definition FlatObject.h:546
char * mFlatBufferContainer
Definition FlatObject.h:322
void destroy()
_______________ Utilities _______________________________________________
Definition FlatObject.h:361
bool isConstructed() const
Tells if the object is constructed.
Definition FlatObject.h:260
static constexpr size_t getBufferAlignmentBytes()
Gives minimal alignment in bytes required for the flat buffer.
Definition FlatObject.h:195
static T * relocatePointer(const char *oldBase, char *newBase, const T *ptr)
Relocates a pointer inside a buffer to the new buffer address.
Definition FlatObject.h:283
ClassDefNV(FlatObject, 1)
Pointer to the flat buffer.
void setActualBufferAddress(char *actualFlatBufferPtr)
_____________ Methods for moving the class with its external buffer to another location _____________...
Definition FlatObject.h:559
static std::string stressTest(T &obj)
Test the flat object functionality for a child class T.
Definition FlatObject.h:423
static int32_t writeToFile(T &obj, TFile &outf, const char *name)
write a child class object to the file
Definition FlatObject.h:492
FlatObject()=default
_____________ Constructors / destructors __________________________
void startConstruction()
_____________ Construction _________
Definition FlatObject.h:354
void moveBufferTo(char *newBufferPtr)
Definition FlatObject.h:408
void finishConstruction(int32_t flatBufferSize)
Definition FlatObject.h:370
bool isBufferInternal() const
Tells if the buffer is internal.
Definition FlatObject.h:263
static constexpr size_t alignSize(size_t sizeBytes, size_t alignmentBytes)
_______________ Generic utilities _______________________________________________
Definition FlatObject.h:275
FlatObject(const FlatObject &)=delete
T * resizeArray(T *&ptr, int32_t oldSize, int32_t newSize, T *newPtr=nullptr)
Definition FlatObject.h:135
void cloneFromObject(const FlatObject &obj, char *newFlatBufferPtr)
Definition FlatObject.h:385
static constexpr size_t getClassAlignmentBytes()
GPUCA_GPUCODE.
Definition FlatObject.h:192
void clearInternalBufferPtr()
Definition FlatObject.h:553
T ** resizeArray(T **&ptr, int32_t oldSize, int32_t newSize, T **newPtr=nullptr)
Definition FlatObject.h:163
ConstructionState
GPUCA_GPUCODE.
Definition FlatObject.h:314
@ InProgress
construction started: temporary memory is reserved
Definition FlatObject.h:317
@ NotConstructed
the object is not constructed
Definition FlatObject.h:315
@ Constructed
the object is constructed, temporary memory is released
Definition FlatObject.h:316
static T * readFromFile(TFile &inpf, const char *name)
read a child class object from the file
Definition FlatObject.h:514
GPUdi() size_t getFlatBufferSize() const
Gives size of the flat buffer.
Definition FlatObject.h:254
GPUdi() const char *getFlatBufferPtr() const
Gives pointer to the flat buffer.
Definition FlatObject.h:257
static constexpr size_t getClassAlignmentBytes()
Definition FlatObject.h:337
GPUdi() size_t getFlatBufferSize() const
Definition FlatObject.h:339
static constexpr size_t getBufferAlignmentBytes()
Definition FlatObject.h:338
const GLdouble * v
Definition glcorearb.h:832
GLuint const GLchar * name
Definition glcorearb.h:781
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition glcorearb.h:2514
a couple of static helper functions to create timestamp values for CCDB queries or override obsolete ...
LOG(info)<< "Compressed in "<< sw.CpuTime()<< " s"