154 lines
5.4 KiB
C++
154 lines
5.4 KiB
C++
/** @file IAlloc.hpp
|
|
*
|
|
* @author: Roland Conybeare, Jul 2025
|
|
**/
|
|
|
|
#pragma once
|
|
|
|
#include <memory>
|
|
#include <cstdint>
|
|
|
|
namespace xo {
|
|
template <typename T>
|
|
using up = std::unique_ptr<T>;
|
|
|
|
class IObject;
|
|
|
|
namespace gc {
|
|
/** @class IAllocator
|
|
* @brief Abstract API for allocation interface
|
|
*
|
|
* Garbage collector support methods:
|
|
* - checkpoint()
|
|
* - assign_member()
|
|
* - alloc_gc_copy()
|
|
*
|
|
* See class GC for copying incremental collector.
|
|
* See class ArenaAlloc for arena allocator
|
|
**/
|
|
class IAlloc {
|
|
public:
|
|
virtual ~IAlloc() {}
|
|
|
|
static inline std::uint32_t alloc_padding(std::size_t z) {
|
|
/* word size for alignment */
|
|
constexpr uint32_t c_bpw = sizeof(std::uintptr_t);
|
|
|
|
/* round up to multiple of c_bpw, but map 0 -> 0
|
|
* (table assuming c_bpw==8)
|
|
*
|
|
* z%c_bpw dz
|
|
* ------------
|
|
* 0 0
|
|
* 1 7
|
|
* 2 6
|
|
* .. ..
|
|
* 7 1
|
|
*/
|
|
std::uint32_t dz = (c_bpw - (z % c_bpw)) % c_bpw;
|
|
z += dz;
|
|
|
|
return dz;
|
|
}
|
|
|
|
static inline std::size_t with_padding(std::size_t z) {
|
|
return z + alloc_padding(z);
|
|
}
|
|
|
|
/** optional name for this allocator; labelling for diagnostics **/
|
|
virtual const std::string & name() const = 0;
|
|
/** allocator size in bytes (up to reserved limit)
|
|
* Includes unallocated mmeory
|
|
**/
|
|
virtual std::size_t size() const = 0;
|
|
/** committed size in bytes **/
|
|
virtual std::size_t committed() const = 0;
|
|
/** number of unallocated bytes available (up to soft limit)
|
|
* from this allocator
|
|
**/
|
|
virtual std::size_t available() const = 0;
|
|
/** number of bytes allocated from this allocator **/
|
|
virtual std::size_t allocated() const = 0;
|
|
/** true iff pointer x comes from this allocator **/
|
|
virtual bool contains(const void * x) const = 0;
|
|
/** true iff object at address @p x was allocated by this allocator,
|
|
* and before checkpoint
|
|
**/
|
|
virtual bool is_before_checkpoint(const void * x) const = 0;
|
|
/** number of bytes allocated before @ref checkpoint **/
|
|
virtual std::size_t before_checkpoint() const = 0;
|
|
/** number of bytes allocated since @ref checkpoint **/
|
|
virtual std::size_t after_checkpoint() const = 0;
|
|
/** @return true iff debug logging enabled **/
|
|
virtual bool debug_flag() const = 0;
|
|
|
|
/** remember allocator state. All currently-allocated addresses xo
|
|
* will satisfy is_before_checkpoint(x). Subsequent allocations x
|
|
* will fail is_before_checkpoint(x), until checkpoint superseded
|
|
* by @ref clear or another call to @ref checkpoint
|
|
**/
|
|
virtual void checkpoint() = 0;
|
|
|
|
/** allocate @p z bytes of memory. returns pointer to first address **/
|
|
virtual std::byte * alloc(std::size_t z) = 0;
|
|
/** reset allocator to empty state. **/
|
|
virtual void clear() = 0;
|
|
|
|
// ----- GC-specific methods -----
|
|
|
|
/** true iff this allocator owns object at address @p src.
|
|
* Use to assist Object::_shallow_move
|
|
**/
|
|
virtual bool check_owned(IObject * /*src*/) const { return false; }
|
|
/** true iff object at address @p src must move as part of
|
|
* in-progress collection phase
|
|
**/
|
|
virtual bool check_move(IObject * /*src*/) const { return false; }
|
|
/** write barrier for collector. perform assignment
|
|
* @code
|
|
* *lhs = rhs
|
|
* @endcode
|
|
* plus additional book keeping if needed (e.g. in @ref GC)
|
|
* Default implementation just does the assignment.
|
|
**/
|
|
virtual void assign_member(IObject * /*parent*/,
|
|
IObject ** lhs,
|
|
IObject * rhs) { *lhs = rhs; }
|
|
/** allocate @p z bytes for copy of object at @p src.
|
|
* Only used in @ref GC. Default implementation asserts and returns nullptr
|
|
**/
|
|
virtual std::byte * alloc_gc_copy(std::size_t /*z*/, const void * /*src*/) {
|
|
// LCOV_EXCL_START
|
|
//assert(false);
|
|
return nullptr;
|
|
// LCOV_EXCL_STOP
|
|
}
|
|
};
|
|
} /*namespace gc*/
|
|
|
|
class MMPtr {
|
|
public:
|
|
explicit MMPtr(gc::IAlloc * mm) : mm_{mm} {}
|
|
|
|
gc::IAlloc * mm_ = nullptr;
|
|
};
|
|
} /*namespace xo*/
|
|
|
|
inline void * operator new (std::size_t z, const xo::MMPtr & mmp) {
|
|
return mmp.mm_->alloc(z);
|
|
}
|
|
|
|
//inline void operator delete (void * p, const MMPtr & mmp) {
|
|
// mmp.mm_->free(reinterpret_cast<std::byte *>(p));
|
|
//}
|
|
|
|
inline void * operator new[] (std::size_t z, const xo::MMPtr & mmp) {
|
|
return mmp.mm_->alloc(z);
|
|
}
|
|
|
|
//inline void operator delete[] (void * p, const MMPtr & mmp) {
|
|
// mmp.mm_->free(reinterpret_cast<std::byte *>(p));
|
|
//}
|
|
|
|
|
|
/* end IAlloc.hpp */
|