#pragma once #include "../engine_plugin_api/plugin_api.h" #define _XKEYCHECK_H #define alignof(x) __alignof(x) namespace stingray_plugin_foundation { // Abstract base class for allocators. // // Allocators can be thread-safe or not, see the separate documentation for each // alloactor. class Allocator { Allocator(const Allocator &); Allocator & operator=(const Allocator &); public: static const int DEFAULT_ALIGN = 4; Allocator() {} virtual ~Allocator() {} // Convenience method for allocating when you don't care about allocated size. virtual void *allocate(size_t size, unsigned align = DEFAULT_ALIGN) = 0; // Frees the memory pointed to by p, the memory must have been allocated by the allocate() // function. Returns the size of the allocated memomry. virtual size_t deallocate(void *p) = 0; }; // Allocator class that wraps the AllocatorApi exposed by the engine's plugin interface. class ApiAllocator : public Allocator { AllocatorObject *_object; AllocatorApi *_api; public: ApiAllocator(AllocatorApi *api, AllocatorObject *object) : _object(object), _api(api) {} ApiAllocator(const ApiAllocator &a) : Allocator(), _object(a._object), _api(a._api) {} ApiAllocator & operator=(const ApiAllocator &a) { _object = a._object; _api = a._api; return *this; } virtual void *allocate(size_t size, unsigned align = DEFAULT_ALIGN) override {return _api->allocate(_object, size, align);} virtual size_t deallocate(void *p) override {return _api->deallocate(_object, p);} AllocatorObject *object() { return _object; } AllocatorApi *api() { return _api; } }; template void make_delete(Allocator &a, T *p) { if (p) { p->~T(); a.deallocate(p); } } // Allocator that allocates from a static buffer. class StaticAllocator : public Allocator { char *_start; char *_p; char *_end; public: StaticAllocator(char *p, char *end) : _start(p), _p(p), _end(end) {} virtual void *allocate(size_t size, unsigned align = DEFAULT_ALIGN) override { if (size == 0) return nullptr; unsigned rem = (_p - (const char *)0) % align; if (rem) _p += (align - rem); char *ret = _p + size > _end ? nullptr : _p; _p += size; return ret; } #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wunused-parameter" size_t deallocate(void *p) override { return 0; } #pragma GCC diagnostic pop char *start() {return _start;} bool out_of_memory() {return _p > _end;} size_t wanted_memory() {return (size_t)(_p - _start);} }; // Allocations released only by destructor class TempAllocator : public ApiAllocator { public: TempAllocator(AllocatorApi *api) : ApiAllocator(api, api->make_temp_allocator()) {} virtual ~TempAllocator() { api()->destroy_temp_allocator(object()); } }; // Add this in the public section of classes to specify that they want to be initialized with an // allocator. #define ALLOCATOR_AWARE typedef int allocator_aware // Macro versions of make_new and make_delete to avoid template combinatorial explosion and // make sure errors are reported in the file where the macro is called. #define MAKE_NEW(a, T, ...) (new ((a).allocate(sizeof(T), alignof(T))) T(__VA_ARGS__)) #define MAKE_DELETE(a, p) (make_delete(a,p)) #define MAKE_DELETE_TYPE(a, T, p) do {if (p) {(p)->~T(); (a).deallocate(p);}} while (0) } // namespace stingray_plugin_foundation