/* * Copyright (c) 2021 Project CHIP Authors * All rights reserved. * * 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 namespace chip { /// Provides an interface over a pool implementation which doesn't expose the size and the actual type of the pool. template class PoolInterface { public: // For convenient use in PoolImpl using Interface = std::tuple; virtual ~PoolInterface() {} virtual U * CreateObject(ConstructorArguments... args) = 0; virtual void ReleaseObject(U * element) = 0; virtual void ReleaseAll() = 0; template Loop ForEachActiveObject(Function && function) { static_assert(std::is_same()))>::value, "The function must take T* and return Loop"); auto proxy = [&](U * target) -> Loop { return function(target); }; return ForEachActiveObjectInner( &proxy, [](void * context, U * target) -> Loop { return (*static_cast(context))(target); }); } template Loop ForEachActiveObject(Function && function) const { static_assert(std::is_same()))>::value, "The function must take const T* and return Loop"); auto proxy = [&](const U * target) -> Loop { return function(target); }; return ForEachActiveObjectInner( &proxy, [](void * context, const U * target) -> Loop { return (*static_cast(context))(target); }); } protected: using Lambda = Loop (*)(void *, U *); using LambdaConst = Loop (*)(void *, const U *); virtual Loop ForEachActiveObjectInner(void * context, Lambda lambda) = 0; virtual Loop ForEachActiveObjectInner(void * context, LambdaConst lambda) const = 0; }; template class PoolProxy; template class PoolProxy> : public PoolInterface { public: static_assert(std::is_base_of::value, "Interface type is not derived from Pool type"); PoolProxy() {} ~PoolProxy() override {} U * CreateObject(ConstructorArguments... args) override { return Impl().CreateObject(std::move(args)...); } void ReleaseObject(U * element) override { Impl().ReleaseObject(static_cast(element)); } void ReleaseAll() override { Impl().ReleaseAll(); } protected: Loop ForEachActiveObjectInner(void * context, typename PoolInterface::Lambda lambda) override { return Impl().ForEachActiveObject([&](T * target) { return lambda(context, static_cast(target)); }); } Loop ForEachActiveObjectInner(void * context, typename PoolInterface::LambdaConst lambda) const override { return Impl().ForEachActiveObject([&](const T * target) { return lambda(context, static_cast(target)); }); } virtual ObjectPool & Impl() = 0; virtual const ObjectPool & Impl() const = 0; }; /* * @brief * Define a implementation of a pool which derive and expose PoolInterface's. * * @tparam T a subclass of element to be allocated. * @tparam N a positive integer max number of elements the pool provides. * @tparam M an ObjectPoolMem constant selecting static vs heap allocation. * @tparam Interfaces a list of parameters which defines PoolInterface's. each interface is defined by a * std::tuple. The PoolImpl is derived from every * PoolInterface, the PoolImpl can be converted to the interface type * and passed around */ template class PoolImpl : public PoolProxy... { public: PoolImpl() {} ~PoolImpl() override {} protected: ObjectPool & Impl() override { return mImpl; } const ObjectPool & Impl() const override { return mImpl; } private: ObjectPool mImpl; }; } // namespace chip