ADOL-C: Automatic Differentiation in C/C++ 2.7.3
Loading...
Searching...
No Matches
bufferstate.h
Go to the documentation of this file.
1#include <algorithm>
2#include <cassert>
3#include <concepts>
4#include <cstddef>
5#include <cstdio>
6#include <memory>
7#include <utility>
8
9#ifndef ADOLC_BUFFER_STATE
10#define ADOLC_BUFFER_STATE
11
12namespace ADOLC::detail {
13
26template <class T, class ElementType>
28 requires(T &buffer, const T &constBuffer, const char *fileName,
29 const char *mode, size_t position, size_t numOnTape) {
30 { buffer.begin() } -> std::same_as<ElementType *>;
31 { constBuffer.begin() } -> std::same_as<const ElementType *>;
32 { buffer.file() } -> std::same_as<FILE *>;
33 { constBuffer.file() } -> std::same_as<FILE *>;
34 { constBuffer.position() } -> std::convertible_to<size_t>;
35 buffer.position(position);
36 { constBuffer.numOnTape() } -> std::convertible_to<size_t>;
37 buffer.numOnTape(numOnTape);
38 buffer.openFile(fileName, mode);
39 buffer.closeFile();
40 };
41
44 int operator()(FILE *file) { return fclose(file); }
45};
46
47inline constexpr auto fileDeleter = FileDeleter{};
48
50struct BufferViewTag {};
51inline constexpr BufferViewTag bufferView;
52
91template <typename T> class BufferState {
92 using FilePtr = std::unique_ptr<FILE, FileDeleter>;
93 FilePtr file_{nullptr, fileDeleter};
94 T *buffer_{nullptr};
95 size_t currentPos_{0};
96 size_t capacity_{0};
97 size_t numOnTape_{0};
98 bool owner_{true};
99
100 void copyBuffer(const BufferState &other) {
101 T *newBuffer = nullptr;
102 if (other.buffer_ != nullptr) {
103 newBuffer = new T[other.capacity_];
104 std::copy_n(other.buffer_, other.capacity_, newBuffer);
105 }
106
107 if (owner_) {
108 delete[] buffer_;
109 }
110 buffer_ = newBuffer;
111 currentPos_ = other.currentPos_;
112 capacity_ = other.capacity_;
113 numOnTape_ = other.numOnTape_;
114 owner_ = true;
115 }
116
117 void moveData(BufferState &&other) {
118 file_ = std::move(other.file_);
119 other.file_ = nullptr;
120 if (owner_) {
121 delete[] buffer_;
122 }
123 buffer_ = other.buffer_;
124 other.buffer_ = nullptr;
125 capacity_ = other.capacity_;
126 currentPos_ = other.currentPos_;
127 numOnTape_ = other.numOnTape_;
128 other.currentPos_ = 0;
129 other.capacity_ = 0;
130 other.numOnTape_ = 0;
131 owner_ = std::exchange(other.owner_, false);
132 }
133
134public:
137 if (owner_) {
138 delete[] buffer_;
139 }
140 }
141
142 BufferState() = default;
143
145 BufferState(T *buffer, size_t capacity)
146 : buffer_(buffer), capacity_(capacity) {};
147
149 BufferState(const BufferState &other) { copyBuffer(other); }
150
159 : buffer_(other.buffer_), currentPos_(other.currentPos_),
160 capacity_(other.capacity_), numOnTape_(other.numOnTape_),
161 owner_(false) {}
162
164 if (this != &other) {
165 copyBuffer(other);
166 file_.reset();
167 }
168 return *this;
169 }
170
172 BufferState(BufferState &&other) noexcept { moveData(std::move(other)); }
173
175 BufferState &operator=(BufferState &&other) noexcept {
176 if (this != &other) {
177 moveData(std::move(other));
178 }
179 return *this;
180 }
181
183 bool isOwner() const { return owner_; }
184
192 if (owner_) {
193 return;
194 }
195 buffer_ = new T[capacity_];
196 owner_ = true;
197 }
199 void resetFile(FILE *file) { file_.reset(file); }
200
202 FILE *file() { return file_.get(); }
203 FILE *file() const { return file_.get(); }
204
206 void closeFile() { file_.reset(); }
207
209 FILE *releaseFile() { return file_.release(); }
210
212 void openFile(const char *fileName, const char *mode) {
213 file_.reset(fopen(fileName, mode));
214 }
215
221 void resetBuffer(T *buffer, size_t capacity) {
222 if (owner_) {
223 delete[] buffer_;
224 }
225 buffer_ = buffer;
226 capacity_ = capacity;
227 currentPos_ = 0;
228 owner_ = true;
229 }
230
232 T *begin() { return buffer_; }
233 const T *begin() const { return buffer_; }
234
242 assert(owner_ && "You can not release a borrowed buffer!");
243 T *buffer = buffer_;
244 buffer_ = nullptr;
245 capacity_ = 0;
246 currentPos_ = 0;
247 return buffer;
248 }
249
251 void allocIfNull(size_t capacity) {
252 if (buffer_ == nullptr) {
253 buffer_ = new T[capacity];
254 capacity_ = capacity;
255 owner_ = true;
256 }
257 }
258
260 size_t position() const { return currentPos_; }
261
263 void position(size_t pos) {
264 assert(pos <= capacity_);
265 currentPos_ = pos;
266 }
267
269 size_t remainingCapacity() const { return capacity_ - currentPos_; }
270
272 size_t capacity() const { return capacity_; }
273
275 size_t numOnTape() const { return numOnTape_; }
276
278 void numOnTape(size_t num) { numOnTape_ = num; }
279
281 const T &operator[](size_t idx) const {
282 assert(idx < capacity_);
283 return buffer_[idx];
284 }
285
287 T &operator[](size_t idx) {
288 assert(idx < capacity_);
289 return buffer_[idx];
290 }
291
293 void writeCurrent(T val) {
294 assert(currentPos_ < capacity_);
295 buffer_[currentPos_] = val;
296 }
297
299 void writeAndAdvance(T val) {
300 writeCurrent(val);
301 advance();
302 }
303
305 T *current() { return buffer_ + currentPos_; }
306 const T *current() const { return buffer_ + currentPos_; }
307
309 void advance() {
310 assert(currentPos_ < capacity_);
311 ++currentPos_;
312 }
313
315 void retreat() {
316 assert(currentPos_ > 0);
317 --currentPos_;
318 }
319
321 T readAndAdvance() { return (*this)[currentPos_++]; }
322
324 T retreatAndRead() { return (*this)[--currentPos_]; }
325};
326
332}; // namespace ADOLC::detail
333#endif // ADOLC_BUFFER_STATE
Buffer and cursor state used by the ADOL-C tape implementation.
Definition bufferstate.h:91
T * current()
Returns a pointer to the element at position().
Definition bufferstate.h:305
const T & operator[](size_t idx) const
Returns a copy of the element at idx.
Definition bufferstate.h:281
void retreat()
Moves the current position back by one element.
Definition bufferstate.h:315
bool isOwner() const
Returns whether this object owns and will delete its buffer allocation.
Definition bufferstate.h:183
BufferState(const BufferState &other, BufferViewTag)
Creates a non-owning view of other's allocation.
Definition bufferstate.h:158
size_t position() const
Returns the current buffer index.
Definition bufferstate.h:260
void closeFile()
Closes the owned FILE handle, if present.
Definition bufferstate.h:206
void advance()
Advances the current position by one element.
Definition bufferstate.h:309
FILE * releaseFile()
Releases the FILE handle without closing it.
Definition bufferstate.h:209
void numOnTape(size_t num)
Sets the number of elements recorded on the tape.
Definition bufferstate.h:278
T * begin()
Returns the beginning of the owned or viewed buffer.
Definition bufferstate.h:232
void resetFile(FILE *file)
Takes ownership of file, closing any previously owned file handle.
Definition bufferstate.h:199
void openFile(const char *fileName, const char *mode)
Opens fileName with mode and owns the resulting FILE handle.
Definition bufferstate.h:212
T readAndAdvance()
Returns the current element, then advances position().
Definition bufferstate.h:321
void allocIfNull(size_t capacity)
Allocates a new owned buffer if no buffer is currently present.
Definition bufferstate.h:251
const T * current() const
Definition bufferstate.h:306
const T * begin() const
Definition bufferstate.h:233
BufferState(T *buffer, size_t capacity)
Takes ownership of an existing heap buffer with the given capacity.
Definition bufferstate.h:145
BufferState & operator=(const BufferState &other)
Definition bufferstate.h:163
void writeAndAdvance(T val)
Stores val at position(), then advances to the next element.
Definition bufferstate.h:299
void allocateAndOwn()
Replaces a view with an uninitialized owned allocation.
Definition bufferstate.h:191
~BufferState()
Deletes the owned buffer and closes the owned file handle, if present.
Definition bufferstate.h:136
BufferState & operator=(BufferState &&other) noexcept
Releases current resources, then moves all resources from other.
Definition bufferstate.h:175
T retreatAndRead()
Moves to the previous element, then returns it.
Definition bufferstate.h:324
void resetBuffer(T *buffer, size_t capacity)
Replaces the buffer pointer.
Definition bufferstate.h:221
FILE * file()
Returns the owned FILE handle without transferring ownership.
Definition bufferstate.h:202
BufferState(BufferState &&other) noexcept
Moves the file handle, buffer, position, capacity, and tape counter.
Definition bufferstate.h:172
size_t numOnTape() const
Returns the number of elements recorded on the tape.
Definition bufferstate.h:275
void position(size_t pos)
Sets the current buffer index.
Definition bufferstate.h:263
void writeCurrent(T val)
Stores val at position().
Definition bufferstate.h:293
BufferState(const BufferState &other)
Creates an independent owning copy. File handles are not copied.
Definition bufferstate.h:149
T & operator[](size_t idx)
Returns a mutable reference to the element at idx.
Definition bufferstate.h:287
T * releaseBuffer()
Releases the owned buffer without deleting it.
Definition bufferstate.h:241
size_t remainingCapacity() const
Returns how many elements fit between position() and capacity().
Definition bufferstate.h:269
FILE * file() const
Definition bufferstate.h:203
size_t capacity() const
Returns the capacity of the owned or viewed buffer.
Definition bufferstate.h:272
Concept describing the primitive buffer/file interface used by tape I/O code.
Definition bufferstate.h:27
Definition bufferstate.h:12
constexpr auto fileDeleter
Definition bufferstate.h:47
constexpr BufferViewTag bufferView
Definition bufferstate.h:51
Selects a non-owning buffer view instead of a deep copy.
Definition bufferstate.h:50
fclose deleter for tape files managed by std::unique_ptr.
Definition bufferstate.h:43
int operator()(FILE *file)
Definition bufferstate.h:44