/* * Copyright (c) 2017-2019 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 // TODO #include #include #include #include namespace utils { template class ObjectPool { class ObjectDeleter { public: ObjectDeleter(ObjectPool *pool = nullptr) : pool_(pool) {} void operator()(T *t) { if (pool_) { pool_->add(t); } else { delete t; } } private: ObjectPool *pool_; }; public: using Ptr = std::unique_ptr; ObjectPool() : destructor_(false) {} ~ObjectPool() { destructor_ = true; } std::pair get() { if (object_pool_.empty()) { return std::make_pair(false, makePtr(nullptr)); } utils::SpinLock::Acquire locked(object_pool_lock_); auto ret = std::move(object_pool_.front()); object_pool_.pop_front(); return std::make_pair(true, std::move(ret)); } void add(T *object) { utils::SpinLock::Acquire locked(object_pool_lock_); if (TRANSPORT_EXPECT_TRUE(!destructor_)) { object_pool_.emplace_back(makePtr(object)); } } Ptr makePtr(T *object) { return Ptr(object, ObjectDeleter(this)); } private: // No copies ObjectPool(const ObjectPool &other) = delete; utils::SpinLock object_pool_lock_; std::deque object_pool_; bool destructor_; }; } // namespace utils