11#include <promeki/config.h>
12#if PROMEKI_ENABLE_CORE
22PROMEKI_NAMESPACE_BEGIN
57 PROMEKI_DATATYPE(MemSpace, DataTypeMemSpace, 1)
60 Error writeToStream(DataStream &s) const;
62 template <uint32_t V> static Result<MemSpace> readFromStream(DataStream &s);
159 using IDList = ::promeki::List<ID>;
181 uint64_t allocCount = 0;
182 uint64_t allocBytes = 0;
183 uint64_t allocFailCount =
185 uint64_t maxAllocBytes =
187 uint64_t releaseCount = 0;
188 uint64_t releaseBytes = 0;
189 uint64_t copyCount = 0;
190 uint64_t copyBytes = 0;
191 uint64_t copyFailCount = 0;
192 uint64_t fillCount = 0;
193 uint64_t fillBytes = 0;
194 uint64_t liveCount = 0;
195 uint64_t liveBytes = 0;
196 uint64_t peakCount = 0;
197 uint64_t peakBytes = 0;
210 uint64_t peakResidentBytes = 0;
213 Atomic<uint64_t> allocCount{0};
214 Atomic<uint64_t> allocBytes{0};
215 Atomic<uint64_t> allocFailCount{0};
216 Atomic<uint64_t> maxAllocBytes{0};
217 Atomic<uint64_t> releaseCount{0};
218 Atomic<uint64_t> releaseBytes{0};
219 Atomic<uint64_t> copyCount{0};
220 Atomic<uint64_t> copyBytes{0};
221 Atomic<uint64_t> copyFailCount{0};
222 Atomic<uint64_t> fillCount{0};
223 Atomic<uint64_t> fillBytes{0};
224 Atomic<uint64_t> liveCount{0};
225 Atomic<uint64_t> liveBytes{0};
226 Atomic<uint64_t> peakCount{0};
227 Atomic<uint64_t> peakBytes{0};
228 Atomic<uint64_t> peakResidentBytes{0};
231 Stats(
const Stats &) =
delete;
232 Stats &operator=(
const Stats &) =
delete;
233 Stats(Stats &&) =
delete;
234 Stats &operator=(Stats &&) =
delete;
245 Snapshot snapshot()
const;
256 void recordAlloc(uint64_t bytes);
264 void recordRelease(uint64_t bytes);
274 void recordResidentBytes(uint64_t bytes);
291 bool (*isHostAccessible)(
292 const MemAllocation &
301 const MemAllocation &src,
const MemAllocation &dst,
304 void *ptr,
size_t bytes,
308 MemDomain::ID domainId =
337 static ID registerType();
361 static void registerData(Ops &&ops);
370 static IDList registeredIDs();
376 inline MemSpace(ID
id = Default);
382 const String &name()
const {
return d->name; }
385 String toString()
const {
return d->name; }
391 ID id()
const {
return d->id; }
403 MemDomain domain()
const {
return MemDomain(d->domainId); }
410 bool isHostAccessible(
const MemAllocation &alloc)
const {
return d->isHostAccessible(alloc); }
426 inline MemAllocation alloc(
size_t bytes,
size_t align)
const;
432 inline void release(MemAllocation &alloc)
const;
447 inline Error copy(
const MemAllocation &src,
const MemAllocation &dst,
size_t bytes)
const;
456 Error fill(
void *ptr,
size_t bytes,
char value)
const {
457 if (ptr ==
nullptr)
return Error::Invalid;
458 Error err = d->fill(ptr, bytes, value);
460 d->stats->fillCount.fetchAndAdd(1);
461 d->stats->fillBytes.fetchAndAdd(bytes);
476 Stats &stats()
const {
return *d->stats; }
482 Stats::Snapshot statsSnapshot()
const {
return d->stats->snapshot(); }
485 void resetStats()
const { d->stats->reset(); }
496 StringList statsReport()
const;
506 static StringList allStatsReport();
515 void logStats()
const;
523 static void logAllStats();
526 const Ops *data()
const {
return d; }
529 bool operator==(
const MemSpace &o)
const {
return d == o.d; }
532 bool operator!=(
const MemSpace &o)
const {
return d != o.d; }
535 const Ops *d =
nullptr;
536 static const Ops *lookup(ID
id);
546struct MemAllocation {
551 void *priv =
nullptr;
554 bool isValid()
const {
return ptr !=
nullptr; }
557inline MemSpace::MemSpace(ID
id) : d(lookup(id)) {}
559inline Error MemSpace::copy(
const MemAllocation &src,
const MemAllocation &dst,
size_t bytes)
const {
560 if (src.ptr ==
nullptr || dst.ptr ==
nullptr) {
561 d->stats->copyFailCount.fetchAndAdd(1);
562 return Error::Invalid;
564 Error err = d->copy(src, dst, bytes);
566 d->stats->copyCount.fetchAndAdd(1);
567 d->stats->copyBytes.fetchAndAdd(bytes);
569 d->stats->copyFailCount.fetchAndAdd(1);
574inline MemAllocation MemSpace::alloc(
size_t bytes,
size_t align)
const {
582 if (bytes == 0)
return a;
584 if (a.ptr !=
nullptr) {
585 d->stats->recordAlloc(
static_cast<uint64_t
>(bytes));
587 d->stats->allocFailCount.fetchAndAdd(1);
592inline void MemSpace::release(MemAllocation &alloc)
const {
593 if (alloc.ptr ==
nullptr)
return;
594 uint64_t bytes =
static_cast<uint64_t
>(alloc.size);
596 d->stats->recordRelease(bytes);
598 alloc.priv =
nullptr;