include/core/CBoostJsonPoolAllocator.h (54 lines of code) (raw):

/* * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one * or more contributor license agreements. Licensed under the Elastic License * 2.0 and the following additional limitation. Functionality enabled by the * files subject to the Elastic License 2.0 may only be used in production when * invoked by an Elasticsearch process with a license key installed that permits * use of machine learning features. You may not use this file except in * compliance with the Elastic License 2.0 and the foregoing additional * limitation. */ #ifndef INCLUDED_ml_core_CBoostJsonPoolAllocator_h #define INCLUDED_ml_core_CBoostJsonPoolAllocator_h #include <boost/json.hpp> #include <memory> #include <vector> namespace json = boost::json; namespace ml { namespace core { namespace { class custom_resource : public boost::container::pmr::memory_resource { public: custom_resource(std::size_t& allocatedBytes) : m_AllocatedBytes{allocatedBytes} {} std::size_t allocatedBytes() const { return m_AllocatedBytes; } private: void* do_allocate(std::size_t bytes, std::size_t /*align*/) override { m_AllocatedBytes += bytes; return ::operator new(bytes); } void do_deallocate(void* ptr, std::size_t bytes, std::size_t /*align*/) override { m_AllocatedBytes -= bytes; return ::operator delete(ptr); } bool do_is_equal(memory_resource const& other) const noexcept override { // since the global allocation and de-allocation functions are used, // any instance of a custom_resource can deallocate memory allocated // by another instance of a logging_resource return dynamic_cast<custom_resource const*>(&other) != nullptr; } private: std::size_t& m_AllocatedBytes; }; } //! \brief //! A custom boost::json memory allocator //! //! DESCRIPTION:\n //! Encapsulates a custom boost::json memory_resource, see https://www.boost.org/doc/libs/1_83_0/libs/json/doc/html/json/allocators/storage_ptr.html //! //! IMPLEMENTATION DECISIONS:\n //! //! Retain documents created to ensure that the associated memory allocator exists for the documents //! lifetime //! //! Clear the allocator on destruction //! class CBoostJsonPoolAllocator { public: using TDocumentWeakPtr = std::weak_ptr<json::object>; using TDocumentPtr = std::shared_ptr<json::object>; using TDocumentPtrVec = std::vector<TDocumentPtr>; public: CBoostJsonPoolAllocator() {} //! \return document pointer suitable for storing in a container //! Note: The document memory is cleaned up once all references to it are destroyed. TDocumentWeakPtr makeStorableDoc() { TDocumentPtr newDoc = std::make_shared<json::object>(m_JsonStoragePointer); m_JsonDocumentStore.push_back(newDoc); return TDocumentWeakPtr(newDoc); } //! \return const reference to the underlying storage pointer const json::storage_ptr& get() const { return m_JsonStoragePointer; } //! \return reference to the underlying storage pointer json::storage_ptr& get() { return m_JsonStoragePointer; } std::size_t getAllocatedBytes() const { return m_AllocatedBytes; } private: std::size_t m_AllocatedBytes{0}; //! storage pointer to use for allocating boost::json objects //! We use a custom resource allocator for more predictable //! and timely allocation/de-allocations, see //! https://www.boost.org/doc/libs/1_83_0/libs/json/doc/html/json/allocators/storage_ptr.html#json.allocators.storage_ptr.user_defined_resource //! for more details. json::storage_ptr m_JsonStoragePointer{ json::make_shared_resource<custom_resource>(m_AllocatedBytes)}; //! Container used to persist boost::json documents TDocumentPtrVec m_JsonDocumentStore; }; } } #endif // INCLUDED_ml_core_CBoostJsonPoolAllocator_h