/* * Copyright (c) 2021 Cisco and/or its affiliates. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #pragma once #include #include #include #include #include namespace transport { namespace core { template class PacketManager : public utils::Singleton> { friend class utils::Singleton>; public: using MemoryPool = utils::FixedBlockAllocator; using RawBuffer = std::pair; struct PacketStorage { std::array packet_and_shared_ptr; std::max_align_t align; }; utils::MemBuf::Ptr getMemBuf() { utils::MemBuf *memory = nullptr; memory = reinterpret_cast(memory_pool_.allocateBlock()); utils::STLAllocator allocator(memory, &memory_pool_); auto offset = offsetof(PacketStorage, align); auto ret = std::allocate_shared( allocator, utils::MemBuf::WRAP_BUFFER, (uint8_t *)memory + offset, 0, chunk_size - offset); ret->clear(); return ret; } utils::MemBuf::Ptr getMemBuf(uint8_t *buffer, std::size_t length) { auto offset = offsetof(PacketStorage, align); auto memory = buffer - offset; utils::STLAllocator allocator( (utils::MemBuf *)memory, &memory_pool_); auto ret = std::allocate_shared( allocator, utils::MemBuf::WRAP_BUFFER, (uint8_t *)buffer, length, chunk_size - offset); return ret; } template < typename PacketType, typename... Args, typename = std::enable_if_t::value>> typename PacketType::Ptr getPacket(Args &&...args) { PacketType *memory = nullptr; memory = reinterpret_cast(memory_pool_.allocateBlock()); utils::STLAllocator allocator(memory, &memory_pool_); auto offset = offsetof(PacketStorage, align); auto ret = std::allocate_shared( allocator, PacketType::CREATE, (uint8_t *)memory + offset, 0, chunk_size - offset, std::forward(args)...); return ret; } std::pair getRawBuffer() { uint8_t *memory = nullptr; memory = reinterpret_cast(memory_pool_.allocateBlock()); auto offset = offsetof(PacketStorage, align); memory += offset; return std::make_pair(memory, chunk_size - offset); } template typename PacketType::Ptr getPacketFromExistingBuffer(uint8_t *buffer, std::size_t length, Args &&...args) { auto offset = offsetof(PacketStorage, align); auto memory = reinterpret_cast(buffer - offset); utils::STLAllocator allocator(memory, &memory_pool_); auto ret = std::allocate_shared( allocator, PacketType::WRAP_BUFFER, (uint8_t *)buffer, length, chunk_size - offset, std::forward(args)...); return ret; } private: PacketManager(std::size_t size = packet_pool_size) : memory_pool_(MemoryPool::getInstance()), size_(0) {} MemoryPool &memory_pool_; std::atomic size_; }; } // end namespace core } // end namespace transport