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
118#ifndef GPUCA_GPUCODE // code invisible on GPU
119
120template <typename T>
121T* resizeArray(T*& ptr, int32_t oldSize, int32_t newSize, T* newPtr = nullptr)
122{
123 // Resize array pointed by ptr. T must be a POD class.
124 // If the non-null newPtr is provided, use it instead of allocating a new one.
125 // In this case it is up to the user to ensure that it has at least newSize slots allocated.
126 // Return original array pointer, so that the user can manage previously allocate memory
127 if (oldSize < 0) {
128 oldSize = 0;
129 }
130 if (newSize > 0) {
131 if (!newPtr) {
132 newPtr = new T[newSize];
133 }
134 int32_t mcp = std::min(newSize, oldSize);
135 if (mcp) {
136 assert(ptr);
137 std::memmove(newPtr, ptr, mcp * sizeof(T));
138 }
139 if (newSize > oldSize) {
140 std::memset(newPtr + mcp, 0, (newSize - oldSize) * sizeof(T));
141 }
142 }
143 T* oldPtr = ptr;
144 ptr = newPtr;
145 return oldPtr;
146}
147
148template <typename T>
149T** resizeArray(T**& ptr, int32_t oldSize, int32_t newSize, T** newPtr = nullptr)
150{
151 // Resize array of pointers pointed by ptr.
152 // If the non-null newPtr is provided, use it instead of allocating a new one.
153 // In this case it is up to the user to ensure that it has at least newSize slots allocated.
154 // Return original array pointer, so that the user can manage previously allocate memory
155 if (oldSize < 0) {
156 oldSize = 0;
157 }
158 if (newSize > 0) {
159 if (!newPtr) {
160 newPtr = new T*[newSize];
161 }
162 int32_t mcp = std::min(newSize, oldSize);
163 std::memmove(newPtr, ptr, mcp * sizeof(T*));
164 if (newSize > oldSize) {
165 std::memset(newPtr + mcp, 0, (newSize - oldSize) * sizeof(T*));
166 }
167 }
168 T** oldPtr = ptr;
169 ptr = newPtr;
170 return oldPtr;
171}
172
173#endif
174
176{
177 public:
179
181#ifndef GPUCA_GPUCODE
182 FlatObject() = default; // No object derrived from FlatObject should be created on the GPU
183 ~FlatObject();
184 FlatObject(const FlatObject&) = delete;
185 FlatObject& operator=(const FlatObject&) = delete;
186#else
187 FlatObject() = delete;
188#endif
189
190 protected:
192
194 static constexpr size_t getClassAlignmentBytes() { return 8; }
195
197 static constexpr size_t getBufferAlignmentBytes() { return 8; }
198
200
202 void startConstruction();
203
207 void finishConstruction(int32_t flatBufferSize);
208
213#ifndef GPUCA_GPUCODE
214 void cloneFromObject(const FlatObject& obj, char* newFlatBufferPtr);
215#endif // !GPUCA_GPUCODE
216
218
219 // Returns an unique pointer to the internal buffer with all the rights. Makes the internal container variable empty.
221
224#ifndef GPUCA_GPUCODE
225 void moveBufferTo(char* newBufferPtr);
226#endif // !GPUCA_GPUCODE
227
229
234 void setActualBufferAddress(char* actualFlatBufferPtr);
235
247 void setFutureBufferAddress(char* futureFlatBufferPtr);
248
250
251 public:
253 void destroy();
254
256 size_t getFlatBufferSize() const { return mFlatBufferSize; }
257
259 const char* getFlatBufferPtr() const { return mFlatBufferPtr; }
260
263
265 bool isBufferInternal() const { return ((mFlatBufferPtr != nullptr) && (mFlatBufferPtr == mFlatBufferContainer)); }
266
267 // Adopt an external pointer as internal buffer
268 void adoptInternalBuffer(char* buf);
269
270 // Hard reset of internal pointer to nullptr without deleting (needed copying an object without releasing)
272
274
275 public:
277 static size_t alignSize(size_t sizeBytes, size_t alignmentBytes)
278 {
279 auto res = sizeBytes % alignmentBytes;
280 return res ? sizeBytes + (alignmentBytes - res) : sizeBytes;
281 }
282
284 template <class T>
285 static T* relocatePointer(const char* oldBase, char* newBase, const T* ptr)
286 {
287 return (ptr != nullptr) ? reinterpret_cast<T*>(newBase + (reinterpret_cast<const char*>(ptr) - oldBase)) : nullptr;
288 }
289
290#if !defined(GPUCA_GPUCODE) && !defined(GPUCA_STANDALONE) // code invisible on GPU
291
293 template <class T, class TFile>
294 static int32_t writeToFile(T& obj, TFile& outf, const char* name);
295
297 template <class T, class TFile>
298 static T* readFromFile(TFile& inpf, const char* name);
299#endif
300
301#if !defined(GPUCA_GPUCODE) // code invisible on GPU
302
304 template <class T>
305 static std::string stressTest(T& obj);
306
308 void printC() const;
309
310#endif
311
312 protected:
314
316 enum ConstructionState : uint32_t {
319 InProgress = 0x2
320 };
321
322 int32_t mFlatBufferSize = 0;
324 char* mFlatBufferContainer = nullptr; //[mFlatBufferSize] Optional container for the flat buffer
325 char* mFlatBufferPtr = nullptr;
326
328};
329
335
336#ifndef GPUCA_GPUCODE // code invisible on GPU
338{
339 destroy();
340}
341
348
357
358inline void FlatObject::finishConstruction(int32_t flatBufferSize)
359{
362
364
365 mFlatBufferSize = flatBufferSize;
367
368 memset((void*)mFlatBufferPtr, 0, mFlatBufferSize); // just to avoid random behavior in case of bugs
369
370 mConstructionMask = (uint32_t)ConstructionState::Constructed; // clear other possible construction flags
371}
372
373inline void FlatObject::cloneFromObject(const FlatObject& obj, char* newFlatBufferPtr)
374{
378 // that we want to relocate the obj to external buffer)
379
380 assert(obj.isConstructed());
381
382 // providing *this with internal buffer as obj makes sens only if we want to conver it to object with PROVIDED external buffer
383 assert(!(!newFlatBufferPtr && obj.mFlatBufferPtr == mFlatBufferPtr && obj.isBufferInternal()));
384
385 char* oldPtr = resizeArray(mFlatBufferPtr, mFlatBufferSize, obj.mFlatBufferSize, newFlatBufferPtr);
386
387 if (isBufferInternal()) {
388 delete[] oldPtr; // delete old buffer if owned
389 }
391 mFlatBufferContainer = newFlatBufferPtr ? nullptr : mFlatBufferPtr; // external buffer is not provided, make object to own the buffer
392 std::memcpy(mFlatBufferPtr, obj.mFlatBufferPtr, obj.mFlatBufferSize);
394}
395
396inline void FlatObject::moveBufferTo(char* newFlatBufferPtr)
397{
399 if (newFlatBufferPtr == mFlatBufferContainer) {
400 return;
401 }
403 delete[] mFlatBufferContainer;
404 mFlatBufferContainer = nullptr;
405 if (!newFlatBufferPtr) { // resizeArray has created own array
407 }
408}
409
410template <class T>
411inline std::string FlatObject::stressTest(T& obj)
412{
416 std::string err;
417
418 if (!obj.isConstructed()) {
419 return "tested object is not constructed!";
420 }
421
422 T tst;
423 tst.cloneFromObject(obj, nullptr);
424 if (!tst.isConstructed() || !tst.isBufferInternal()) {
425 return "error at cloneFromObject()!";
426 }
427
428 obj.destroy();
429
430 char* buf0 = tst.releaseInternalBuffer();
431 char* buf1 = new char[tst.getFlatBufferSize()];
432 char* buf2 = new char[tst.getFlatBufferSize()];
433 std::memcpy(buf1, tst.getFlatBufferPtr(), tst.getFlatBufferSize());
434 tst.setActualBufferAddress(buf1);
435 delete[] buf0;
436
437 tst.setFutureBufferAddress(buf2);
438 std::memcpy(buf2, buf1, tst.getFlatBufferSize());
439 delete[] buf1;
440
441 if (tst.isBufferInternal()) {
442 return err = "error, buffer should be external!";
443 }
444
445 tst.adoptInternalBuffer(buf2);
446 if (!tst.isBufferInternal()) {
447 return err = "error, buffer should be internal!";
448 }
449
450 obj.cloneFromObject(tst, nullptr);
451 if (!obj.isBufferInternal()) {
452 return err = "error, buffer should be internal!";
453 }
454
455 return err;
456}
457
458inline void FlatObject::printC() const
459{
461 bool lfdone = false;
462 for (int32_t i = 0; i < mFlatBufferSize; i++) {
463 uint8_t v = mFlatBufferPtr[i];
464 lfdone = false;
465 printf("0x%02x ", v);
466 if (i && ((i + 1) % 20) == 0) {
467 printf("\n");
468 lfdone = true;
469 }
470 }
471 if (!lfdone) {
472 printf("\n");
473 }
474}
475
476#endif // GPUCA_GPUCODE
477
478#if !defined(GPUCA_GPUCODE) && !defined(GPUCA_STANDALONE) // code invisible on GPU
479template <class T, class TFile>
480inline int32_t FlatObject::writeToFile(T& obj, TFile& outf, const char* name)
481{
483 assert(obj.isConstructed());
484
485 if (outf.IsZombie()) {
486 LOG(error) << "Failed to write to file " << outf.GetName();
487 return -1;
488 }
489
490 bool isBufferExternal = !obj.isBufferInternal();
491 if (isBufferExternal) {
492 obj.adoptInternalBuffer(obj.mFlatBufferPtr);
493 }
494 outf.WriteObjectAny(&obj, T::Class(), name);
495 if (isBufferExternal) {
496 obj.clearInternalBufferPtr();
497 }
498 return 0;
499}
500
501template <class T, class TFile>
502inline T* FlatObject::readFromFile(TFile& inpf, const char* name)
503{
505
506 if (inpf.IsZombie()) {
507 LOG(error) << "Failed to read from file " << inpf.GetName();
508 return nullptr;
509 }
510 T* pobj = reinterpret_cast<T*>(inpf.GetObjectChecked(name, T::Class()));
511 if (!pobj) {
512 LOG(error) << "Failed to load " << name << " from " << inpf.GetName();
513 return nullptr;
514 }
515 if (pobj->mFlatBufferSize > 0 && pobj->mFlatBufferContainer == nullptr) {
516 LOG(error) << "Failed to load " << name << " from " << inpf.GetName() << ": empty flat buffer container";
517 return nullptr;
518 }
519 pobj->setActualBufferAddress(pobj->mFlatBufferContainer);
520 return pobj;
521}
522#endif // GPUCA_GPUCODE || GPUCA_STANDALONE
523
524#ifndef GPUCA_GPUCODE_DEVICE
525
527{
528 // returns an pointer to the internal buffer. Makes the internal container variable empty.
529 char* contPtr = mFlatBufferContainer;
530 mFlatBufferContainer = nullptr;
531 return contPtr;
532}
533
535{
536 // buf becomes the new internal buffer, after it was already set as new setActualBufferAddress
537 assert((mFlatBufferPtr == buf));
539}
540
542{
543 // we just release the internal buffer ressetting it to nullptr
544 mFlatBufferContainer = nullptr;
545}
546
547inline void FlatObject::setActualBufferAddress(char* actualFlatBufferPtr)
548{
553
554 mFlatBufferPtr = actualFlatBufferPtr;
555}
556
557inline void FlatObject::setFutureBufferAddress(char* futureFlatBufferPtr)
558{
563
564 assert(!isBufferInternal());
565 mFlatBufferPtr = futureFlatBufferPtr;
566#ifndef GPUCA_GPUCODE // code invisible on GPU
567 delete[] mFlatBufferContainer; // for a case..
568#endif // !GPUCA_GPUCODE
569 mFlatBufferContainer = nullptr;
570}
571
572#endif //GPUCA_GPUCODE_DEVICE
573
574} // namespace gpu
575} // namespace o2
576
577#endif
int32_t i
uint32_t res
Definition RawData.h:0
TBranch * ptr
GPUCA_GPUCODE.
Definition FlatObject.h:176
char * releaseInternalBuffer()
_____________ Methods for making the data buffer external __________________________
Definition FlatObject.h:526
void setFutureBufferAddress(char *futureFlatBufferPtr)
Definition FlatObject.h:557
uint32_t mConstructionMask
mask for constructed object members, first two bytes are used by this class
Definition FlatObject.h:323
int32_t mFlatBufferSize
size of the flat buffer
Definition FlatObject.h:322
FlatObject & operator=(const FlatObject &)=delete
void printC() const
Print the content of the flat buffer.
Definition FlatObject.h:458
void adoptInternalBuffer(char *buf)
Definition FlatObject.h:534
char * mFlatBufferContainer
Definition FlatObject.h:324
void destroy()
_______________ Utilities _______________________________________________
Definition FlatObject.h:349
static size_t alignSize(size_t sizeBytes, size_t alignmentBytes)
_______________ Generic utilities _______________________________________________
Definition FlatObject.h:277
bool isConstructed() const
Tells if the object is constructed.
Definition FlatObject.h:262
static constexpr size_t getBufferAlignmentBytes()
Gives minimal alignment in bytes required for the flat buffer.
Definition FlatObject.h:197
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:285
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:547
static std::string stressTest(T &obj)
Test the flat object functionality for a child class T.
Definition FlatObject.h:411
static int32_t writeToFile(T &obj, TFile &outf, const char *name)
write a child class object to the file
Definition FlatObject.h:480
FlatObject()=default
_____________ Constructors / destructors __________________________
void startConstruction()
_____________ Construction _________
Definition FlatObject.h:342
void moveBufferTo(char *newBufferPtr)
Definition FlatObject.h:396
void finishConstruction(int32_t flatBufferSize)
Definition FlatObject.h:358
bool isBufferInternal() const
Tells if the buffer is internal.
Definition FlatObject.h:265
FlatObject(const FlatObject &)=delete
void cloneFromObject(const FlatObject &obj, char *newFlatBufferPtr)
Definition FlatObject.h:373
static constexpr size_t getClassAlignmentBytes()
_____________ Memory alignment __________________________
Definition FlatObject.h:194
void clearInternalBufferPtr()
Definition FlatObject.h:541
size_t getFlatBufferSize() const
Gives size of the flat buffer.
Definition FlatObject.h:256
ConstructionState
GPUCA_GPUCODE.
Definition FlatObject.h:316
@ InProgress
construction started: temporary memory is reserved
Definition FlatObject.h:319
@ NotConstructed
the object is not constructed
Definition FlatObject.h:317
@ Constructed
the object is constructed, temporary memory is released
Definition FlatObject.h:318
static T * readFromFile(TFile &inpf, const char *name)
read a child class object from the file
Definition FlatObject.h:502
const char * getFlatBufferPtr() const
Gives pointer to the flat buffer.
Definition FlatObject.h:259
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
T * resizeArray(T *&ptr, int32_t oldSize, int32_t newSize, T *newPtr=nullptr)
Definition FlatObject.h:121
a couple of static helper functions to create timestamp values for CCDB queries or override obsolete ...
LOG(info)<< "Compressed in "<< sw.CpuTime()<< " s"