FMpiBufferWriter.hpp 4.74 KB
Newer Older
PIACIBELLO Cyrille's avatar
PIACIBELLO Cyrille committed
1
// ===================================================================================
2 3 4 5
// Copyright ScalFmm 2016 INRIA, Olivier Coulaud, Bérenger Bramas,
// Matthias Messner olivier.coulaud@inria.fr, berenger.bramas@inria.fr
// This software is a computer program whose purpose is to compute the
// FMM.
6
//
7
// This software is governed by the CeCILL-C and LGPL licenses and
8
// abiding by the rules of distribution of free software.
9 10 11
// An extension to the license is given to allow static linking of scalfmm
// inside a proprietary application (no matter its license).
// See the main license file for more details.
12
//
PIACIBELLO Cyrille's avatar
PIACIBELLO Cyrille committed
13 14 15
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 17 18
// GNU General Public and CeCILL-C Licenses for more details.
// "http://www.cecill.info".
// "http://www.gnu.org/licenses".
PIACIBELLO Cyrille's avatar
PIACIBELLO Cyrille committed
19 20 21 22
// ===================================================================================
#ifndef FMPIBUFFERWRITER_HPP
#define FMPIBUFFERWRITER_HPP

23
#include <memory>
PIACIBELLO Cyrille's avatar
PIACIBELLO Cyrille committed
24
#include "../Utils/FMpi.hpp"
25
#include "FAbstractBuffer.hpp"
26
#include "../Utils/FAssert.hpp"
PIACIBELLO Cyrille's avatar
PIACIBELLO Cyrille committed
27

28 29
/** @author Cyrille Piacibello, Berenger Bramas
 * This class provide the same features as FBufferWriter
PIACIBELLO Cyrille's avatar
PIACIBELLO Cyrille committed
30 31 32 33 34
 *
 * Put some data
 * then insert back if needed
 * finally use data pointer as you like
 */
35
class FMpiBufferWriter : public FAbstractBufferWriter {
36
    FSize arrayCapacity;              //< Allocated Space
BRAMAS Berenger's avatar
BRAMAS Berenger committed
37
    std::unique_ptr<char[]> array;  //< Allocated Array
38
    FSize currentIndex;               //< Currently filled space
BRAMAS Berenger's avatar
BRAMAS Berenger committed
39 40

    /** Test and exit if not enought space */
41 42
    void expandIfNeeded(const FSize requestedSpace) {
        if( arrayCapacity < currentIndex + requestedSpace){
43
            arrayCapacity = FSize(double(currentIndex + requestedSpace + 1) * 1.5);
BRAMAS Berenger's avatar
BRAMAS Berenger committed
44 45 46 47
            char* arrayTmp = new char[arrayCapacity];
            memcpy(arrayTmp, array.get(), sizeof(char)*currentIndex);
            array.reset(arrayTmp);
        }
PIACIBELLO Cyrille's avatar
PIACIBELLO Cyrille committed
48 49
    }

50
public:
BRAMAS Berenger's avatar
BRAMAS Berenger committed
51
    /** Constructor with a default arrayCapacity of 512 bytes */
52
    explicit FMpiBufferWriter(const FSize inDefaultCapacity = 1024):
BRAMAS Berenger's avatar
BRAMAS Berenger committed
53 54
        arrayCapacity(inDefaultCapacity),
        array(new char[inDefaultCapacity]),
BRAMAS Berenger's avatar
BRAMAS Berenger committed
55 56 57
        currentIndex(0)
    {}

BRAMAS Berenger's avatar
BRAMAS Berenger committed
58 59

    /** To change the capacity (but reset the head to 0 if size if lower) */
60
    void resize(const FSize newCapacity){
BRAMAS Berenger's avatar
BRAMAS Berenger committed
61 62 63 64 65 66 67 68 69
        if(newCapacity != arrayCapacity){
            arrayCapacity = newCapacity;
            char* arrayTmp = new char[arrayCapacity];
            currentIndex = (currentIndex < arrayCapacity ? currentIndex : arrayCapacity-1);
            memcpy(arrayTmp, array.get(), sizeof(char)*currentIndex);
            array.reset(arrayTmp);
        }
    }

BRAMAS Berenger's avatar
BRAMAS Berenger committed
70 71 72 73 74
    /** Destructor */
    virtual ~FMpiBufferWriter(){
    }

    /** Get allocated memory pointer */
75
    char* data() override {
BRAMAS Berenger's avatar
BRAMAS Berenger committed
76 77 78 79
        return array.get();
    }

    /** Get allocated memory pointer */
80
    const char* data() const override  {
BRAMAS Berenger's avatar
BRAMAS Berenger committed
81 82 83 84
        return array.get();
    }

    /** Get the filled space */
85
    FSize getSize() const override  {
BRAMAS Berenger's avatar
BRAMAS Berenger committed
86 87 88 89
        return currentIndex;
    }

    /** Get the allocated space */
90
    FSize getCapacity() const {
BRAMAS Berenger's avatar
BRAMAS Berenger committed
91 92 93 94 95 96
        return arrayCapacity;
    }

    /** Write data by packing cpy */
    template <class ClassType>
    void write(const ClassType& object){
BRAMAS Berenger's avatar
BRAMAS Berenger committed
97
        expandIfNeeded(sizeof(ClassType));
98 99
        memcpy(&array[currentIndex], &object, sizeof(ClassType));
        currentIndex += sizeof(ClassType);
BRAMAS Berenger's avatar
BRAMAS Berenger committed
100 101 102
    }

    /**
PIACIBELLO Cyrille's avatar
PIACIBELLO Cyrille committed
103 104
   * Allow to pass rvalue to write
   */
BRAMAS Berenger's avatar
BRAMAS Berenger committed
105 106
    template <class ClassType>
    void write(const ClassType&& object){
BRAMAS Berenger's avatar
BRAMAS Berenger committed
107
        expandIfNeeded(sizeof(ClassType));
108 109
        memcpy(&array[currentIndex], &object, sizeof(ClassType));
        currentIndex += sizeof(ClassType);
PIACIBELLO Cyrille's avatar
PIACIBELLO Cyrille committed
110
    }
111

BRAMAS Berenger's avatar
BRAMAS Berenger committed
112 113
    /** Write back, position + sizeof(object) has to be < size */
    template <class ClassType>
114
    void writeAt(const FSize position, const ClassType& object){
BRAMAS Berenger's avatar
BRAMAS Berenger committed
115 116
        FAssertLF(position+FSize(sizeof(ClassType)) <= currentIndex);
        memcpy(&array[position], &object, sizeof(ClassType));
BRAMAS Berenger's avatar
BRAMAS Berenger committed
117 118 119
    }

    /** Write an array
PIACIBELLO Cyrille's avatar
PIACIBELLO Cyrille committed
120 121
   * Warning : inSize is a number of ClassType object to write, not a size in bytes
   */
BRAMAS Berenger's avatar
BRAMAS Berenger committed
122
    template <class ClassType>
123
    void write(const ClassType* const objects, const FSize inSize){
BRAMAS Berenger's avatar
BRAMAS Berenger committed
124
        expandIfNeeded(sizeof(ClassType) * inSize);
125 126
        memcpy(&array[currentIndex], objects, sizeof(ClassType)*inSize);
        currentIndex += sizeof(ClassType)*inSize;
BRAMAS Berenger's avatar
BRAMAS Berenger committed
127 128 129 130 131 132 133 134 135 136
    }

    /** Equivalent to write */
    template <class ClassType>
    FMpiBufferWriter& operator<<(const ClassType& object){
        write(object);
        return *this;
    }

    /** Reset the writing index, but do not change the arrayCapacity */
137
    void reset() override {
BRAMAS Berenger's avatar
BRAMAS Berenger committed
138 139
        currentIndex = 0;
    }
PIACIBELLO Cyrille's avatar
PIACIBELLO Cyrille committed
140 141 142 143
};


#endif // FBUFFERWRITER_HPP