libpromeki 1.0.0-alpha
PROfessional MEdia toolKIt
 
Loading...
Searching...
No Matches
buffer.h
Go to the documentation of this file.
1
8#pragma once
9
10
11#include <promeki/config.h>
12#if PROMEKI_ENABLE_CORE
13#include <cassert>
14#include <cstddef>
15#include <cstdint>
16#include <promeki/namespace.h>
17#include <promeki/list.h>
18#include <promeki/error.h>
19#include <promeki/result.h>
20#include <promeki/sharedptr.h>
21#include <promeki/memspace.h>
22#include <promeki/memdomain.h>
24#include <promeki/bufferimpl.h>
27
28PROMEKI_NAMESPACE_BEGIN
29
30class String;
31
103class Buffer {
104 public:
106 using List = ::promeki::List<Buffer>;
107
112 static size_t getPageSize();
113
115 static const size_t DefaultAlign;
116
118 Buffer() = default;
119
135 Buffer(size_t sz, size_t an = DefaultAlign, const MemSpace &ms = MemSpace::Default)
136 : _d(makeBufferImpl(ms, sz, an)) {}
137
153 static Buffer wrapHost(void *p, size_t sz, size_t an = 0, const MemSpace &ms = MemSpace::Default);
154
184 static Buffer wrapDmabuf(int fd, size_t sz, size_t an = 0);
185
192 static Buffer fromImpl(BufferImpl *impl) {
193 Buffer b;
194 if (impl != nullptr) b._d = BufferImplPtr::takeOwnership(impl);
195 return b;
196 }
197
216 static Result<Buffer> fromHex(const String &hex);
217
231 String toHex(const String &sep) const;
232
234 String toHex() const;
235
242 bool isValid() const { return _d.isValid() && _d->allocSize() > 0; }
243
263 void *data() {
264 if (!_d.isValid()) return nullptr;
265 void *base = _d->mappedHostData();
266 if (base == nullptr) return nullptr;
267 return static_cast<uint8_t *>(base) + _d->shift();
268 }
269
271 const void *data() const {
272 if (!_d.isValid()) return nullptr;
273 const void *base = _d->mappedHostData();
274 if (base == nullptr) return nullptr;
275 return static_cast<const uint8_t *>(base) + _d->shift();
276 }
277
287 void *odata() {
288 if (!_d.isValid()) return nullptr;
289 return _d->mappedHostData();
290 }
291
293 const void *odata() const {
294 if (!_d.isValid()) return nullptr;
295 return _d->mappedHostData();
296 }
297
304 size_t size() const { return _d.isValid() ? _d->logicalSize() : 0; }
305
314 void setSize(size_t s) const {
315 assert(s <= availSize());
316 if (_d.isValid()) _d->setLogicalSize(s);
317 // setLogicalSize is a const method on BufferImpl
318 // (mutates a `mutable` member), so `_d->` const
319 // operator-> reaches it without modify().
320 }
321
327 size_t availSize() const {
328 if (!_d.isValid()) return 0;
329 size_t total = _d->allocSize();
330 size_t shift = _d->shift();
331 return shift > total ? 0 : total - shift;
332 }
333
335 size_t allocSize() const { return _d.isValid() ? _d->allocSize() : 0; }
336
338 size_t align() const { return _d.isValid() ? _d->align() : 0; }
339
346 MemSpace memSpace() const { return _d.isValid() ? _d->memSpace() : MemSpace(MemSpace::System); }
347
359 void shiftData(size_t bytes) {
360 assert(_d.isValid());
361 assert(bytes <= _d->allocSize());
362 _d.modify()->setShift(bytes);
363 }
364
368 size_t shift() const { return _d.isValid() ? _d->shift() : 0; }
369
370 // ---- Mapping ----
371
376 bool isMapped(MemDomain domain = MemDomain::Host) const {
377 return _d.isValid() && _d->isMapped(domain);
378 }
379
385 bool isHostAccessible() const { return isMapped(MemDomain::Host); }
386
398 BufferRequest mapAcquire(MemDomain domain = MemDomain::Host, MapFlags flags = MapFlags::Read) {
399 if (!_d.isValid()) return BufferRequest::resolved(Error::Invalid);
400 return _d.modify()->mapAcquire(domain, flags);
401 }
402
413 BufferRequest mapRelease(MemDomain domain = MemDomain::Host) {
414 if (!_d.isValid()) return BufferRequest::resolved(Error::Invalid);
415 return _d.modify()->mapRelease(domain);
416 }
417
418 // ---- Mutation ----
419
428 Error fill(char value) const {
429 if (!_d.isValid()) return Error::Invalid;
430 return _d.modify()->fill(value, _d->shift(), availSize());
431 }
432
445 Error copyFrom(const void *src, size_t bytes, size_t offset = 0) const;
446
469 BufferRequest copyTo(Buffer &dst, size_t bytes, size_t srcOffset = 0, size_t dstOffset = 0) const;
470
471 // ---- Detach ----
472
483 void ensureExclusive() {
484 if (!_d.isValid()) return;
485 if (_d.referenceCount() < 2) return;
486 if (!_d->canClone()) return;
487 _d.detach();
488 }
489
499 Error ensureExclusiveError() {
500 if (!_d.isValid()) return Error::Invalid;
501 if (_d.referenceCount() < 2) return Error::Ok;
502 if (!_d->canClone()) return Error::NotSupported;
503 _d.detach();
504 return Error::Ok;
505 }
506
508 bool isExclusive() const { return _d.isValid() && _d.referenceCount() < 2; }
509
519 bool isShared() const { return _d.isValid() && _d.referenceCount() >= 2; }
520
542 [[nodiscard]] Error seal() const {
543 if (!_d.isValid()) return Error::Invalid;
544 return _d->seal();
545 }
546
556 size_t residentBytes() const {
557 return _d.isValid() ? _d->residentBytes() : 0;
558 }
559
571 bool isCowBacked() const {
572 return _d.isValid() && _d->isCowBacked();
573 }
574
582 const BufferImplPtr &impl() const { return _d; }
583
593 int dmabufFd() const;
594
613 bool operator==(const Buffer &o) const;
614
616 bool operator!=(const Buffer &o) const { return !(*this == o); }
617
619 explicit operator bool() const { return _d.isValid(); }
620
621 private:
622 // mutable so const-on-method mutators (setSize, fill,
623 // copyFrom) can call _d.modify() to reach the
624 // BufferImpl's non-const interface without
625 // const_cast. The Buffer wrapper's own identity (the
626 // impl pointer) is never reassigned through a const
627 // path; only the pointed-to BufferImpl is mutated.
628 mutable BufferImplPtr _d;
629};
630
631PROMEKI_NAMESPACE_END
632
633#endif // PROMEKI_ENABLE_CORE