DYTSrouce/Tool/matlab/include/coder/target_services/MemoryServiceBase.hpp
2024-11-22 23:19:31 +08:00

128 lines
3.3 KiB
C++

/* Copyright 2013 The MathWorks, Inc. */
#ifndef coder_tgtsvc_MemoryServiceBase_hpp
#define coder_tgtsvc_MemoryServiceBase_hpp
#include <stdint.h>
#include <stdlib.h>
#include "coder_target_services_spec.h"
#include "SList.hpp"
#include "StatusFlags.hpp"
namespace coder { namespace tgtsvc {
namespace detail {
struct Chunk : public SListBaseHook<> {
enum {
POOL_INDEX_OFFSET = 0,
ALLOCATED_OFFSET = 1,
IS_ALLOCATED = 1
};
uint8_t poolIndex() const { return header()[POOL_INDEX_OFFSET]; }
void poolIndex(uint8_t v) { header()[POOL_INDEX_OFFSET] = v; }
bool allocated() const { return header()[ALLOCATED_OFFSET] == 1; }
void allocated(bool v) { header()[ALLOCATED_OFFSET] = (uint8_t)v; }
const uint8_t *header() const {
const uint8_t *p = reinterpret_cast<const uint8_t*>(this-1);
return p;
}
uint8_t *header() {
return const_cast<uint8_t*>(static_cast<const Chunk*>(this)->header());
}
static Chunk *fromHeader(void *p) {
uint8_t *b = static_cast<uint8_t*>(p);
b += sizeof(void*);
return reinterpret_cast<Chunk*>(b);
}
};
}
template <class Derived>
class CODER_TARGET_SERVICES_EXPORT_CLASS MemoryServiceBase
{
public:
explicit MemoryServiceBase(const uint16_t *poolSizes, uint8_t poolCnt) :
poolSizes_(poolSizes), poolCount_(poolCnt)
{
for (uint8_t i=0; i<poolCount(); ++i) {
assert(poolSize(i) % sizeof(void*) == 0);
if (i>0) assert(poolSize(i) > poolSize(i-1));
else assert(poolSize(i) >= sizeof(void*));
}
}
~MemoryServiceBase() {
}
uint16_t poolSize(uint8_t poolIdx) const {
assert(poolIdx < poolCount_);
return poolSizes_[poolIdx];
}
uint8_t poolCount() const { return poolCount_; }
void *alloc(size_t request) throw() {
uint8_t poolIdx = whichPool(request);
detail::Chunk *c = NULL;
if (poolIdx < poolCount()) {
c = static_cast<Derived*>(this)->popChunk(poolIdx);
if (c == NULL) {
c = static_cast<Derived*>(this)->allocChunk(poolIdx);
}
}
if (c != NULL) {
c->poolIndex(poolIdx);
c->allocated(true);
} else {
StatusFlags::instance().set(StatusFlags::MEMORY_ALLOCATION_FAILED);
}
return c;
}
void free(void *p) {
detail::Chunk *c = reinterpret_cast<detail::Chunk*>(p);
assert(c != NULL && c->allocated() && c->poolIndex() < poolCount());
c->allocated(false);
static_cast<Derived*>(this)->pushChunk(c);
}
uint16_t capacity(const void *p) const {
const detail::Chunk *c = reinterpret_cast<const detail::Chunk*>(p);
assert(c != NULL && c->allocated() && c->poolIndex() < poolCount());
uint8_t poolIdx = c->poolIndex();
return poolSize(poolIdx);
}
uint16_t maxCapacity() const { return poolSize(poolCount()-1); }
private:
const uint16_t *poolSizes_;
uint8_t poolCount_;
uint8_t whichPool(size_t requestSize) {
uint8_t r = 0;
while (r < poolCount() && poolSize(r) < requestSize) ++r;
return r;
}
MemoryServiceBase(const MemoryServiceBase &cpy);
MemoryServiceBase &operator=(const MemoryServiceBase &cpy);
};
}}
#endif