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);
180 using IDList = ::promeki::List<ID>;
202 uint64_t allocCount = 0;
203 uint64_t allocBytes = 0;
204 uint64_t allocFailCount =
206 uint64_t maxAllocBytes =
208 uint64_t releaseCount = 0;
209 uint64_t releaseBytes = 0;
210 uint64_t copyCount = 0;
211 uint64_t copyBytes = 0;
212 uint64_t copyFailCount = 0;
213 uint64_t fillCount = 0;
214 uint64_t fillBytes = 0;
215 uint64_t liveCount = 0;
216 uint64_t liveBytes = 0;
217 uint64_t peakCount = 0;
218 uint64_t peakBytes = 0;
231 uint64_t peakResidentBytes = 0;
234 Atomic<uint64_t> allocCount{0};
235 Atomic<uint64_t> allocBytes{0};
236 Atomic<uint64_t> allocFailCount{0};
237 Atomic<uint64_t> maxAllocBytes{0};
238 Atomic<uint64_t> releaseCount{0};
239 Atomic<uint64_t> releaseBytes{0};
240 Atomic<uint64_t> copyCount{0};
241 Atomic<uint64_t> copyBytes{0};
242 Atomic<uint64_t> copyFailCount{0};
243 Atomic<uint64_t> fillCount{0};
244 Atomic<uint64_t> fillBytes{0};
245 Atomic<uint64_t> liveCount{0};
246 Atomic<uint64_t> liveBytes{0};
247 Atomic<uint64_t> peakCount{0};
248 Atomic<uint64_t> peakBytes{0};
249 Atomic<uint64_t> peakResidentBytes{0};
252 Stats(
const Stats &) =
delete;
253 Stats &operator=(
const Stats &) =
delete;
254 Stats(Stats &&) =
delete;
255 Stats &operator=(Stats &&) =
delete;
266 Snapshot snapshot()
const;
277 void recordAlloc(uint64_t bytes);
285 void recordRelease(uint64_t bytes);
295 void recordResidentBytes(uint64_t bytes);
312 bool (*isHostAccessible)(
313 const MemAllocation &
322 const MemAllocation &src,
const MemAllocation &dst,
325 void *ptr,
size_t bytes,
329 MemDomain::ID domainId =
358 static ID registerType();
382 static void registerData(Ops &&ops);
391 static IDList registeredIDs();
397 inline MemSpace(ID
id = Default);
403 const String &name()
const {
return d->name; }
406 String toString()
const {
return d->name; }
412 ID id()
const {
return d->id; }
424 MemDomain domain()
const {
return MemDomain(d->domainId); }
431 bool isHostAccessible(
const MemAllocation &alloc)
const {
return d->isHostAccessible(alloc); }
447 inline MemAllocation alloc(
size_t bytes,
size_t align)
const;
453 inline void release(MemAllocation &alloc)
const;
468 inline Error copy(
const MemAllocation &src,
const MemAllocation &dst,
size_t bytes)
const;
477 Error fill(
void *ptr,
size_t bytes,
char value)
const {
478 if (ptr ==
nullptr)
return Error::Invalid;
479 Error err = d->fill(ptr, bytes, value);
481 d->stats->fillCount.fetchAndAdd(1);
482 d->stats->fillBytes.fetchAndAdd(bytes);
497 Stats &stats()
const {
return *d->stats; }
503 Stats::Snapshot statsSnapshot()
const {
return d->stats->snapshot(); }
506 void resetStats()
const { d->stats->reset(); }
517 StringList statsReport()
const;
527 static StringList allStatsReport();
536 void logStats()
const;
544 static void logAllStats();
547 const Ops *data()
const {
return d; }
550 bool operator==(
const MemSpace &o)
const {
return d == o.d; }
553 bool operator!=(
const MemSpace &o)
const {
return d != o.d; }
556 const Ops *d =
nullptr;
557 static const Ops *lookup(ID
id);
567struct MemAllocation {
572 void *priv =
nullptr;
575 bool isValid()
const {
return ptr !=
nullptr; }
578inline MemSpace::MemSpace(ID
id) : d(lookup(id)) {}
580inline Error MemSpace::copy(
const MemAllocation &src,
const MemAllocation &dst,
size_t bytes)
const {
581 if (src.ptr ==
nullptr || dst.ptr ==
nullptr) {
582 d->stats->copyFailCount.fetchAndAdd(1);
583 return Error::Invalid;
585 Error err = d->copy(src, dst, bytes);
587 d->stats->copyCount.fetchAndAdd(1);
588 d->stats->copyBytes.fetchAndAdd(bytes);
590 d->stats->copyFailCount.fetchAndAdd(1);
595inline MemAllocation MemSpace::alloc(
size_t bytes,
size_t align)
const {
603 if (bytes == 0)
return a;
605 if (a.ptr !=
nullptr) {
606 d->stats->recordAlloc(
static_cast<uint64_t
>(bytes));
608 d->stats->allocFailCount.fetchAndAdd(1);
613inline void MemSpace::release(MemAllocation &alloc)
const {
614 if (alloc.ptr ==
nullptr)
return;
615 uint64_t bytes =
static_cast<uint64_t
>(alloc.size);
617 d->stats->recordRelease(bytes);
619 alloc.priv =
nullptr;