.. _program_listing_file__tmp_ws_src_fastrtps_include_fastrtps_utils_ProxyPool.hpp: Program Listing for File ProxyPool.hpp ====================================== |exhale_lsh| :ref:`Return to documentation for file ` (``/tmp/ws/src/fastrtps/include/fastrtps/utils/ProxyPool.hpp``) .. |exhale_lsh| unicode:: U+021B0 .. UPWARDS ARROW WITH TIP LEFTWARDS .. code-block:: cpp // Copyright 2022 Proyectos y Sistemas de Mantenimiento SL (eProsima). // // 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. #ifndef FASTRTPS_UTILS_PROXY_POOL_HPP_ #define FASTRTPS_UTILS_PROXY_POOL_HPP_ #include #include #include #include #include #include #if defined(__has_include) && __has_include() # include #endif // if defined(__has_include) && __has_include() namespace eprosima { // unnamed namespace for isolation namespace { // Detect if integer_sequence is availalbe #if defined(__cpp_lib_integer_sequence) \ && ((__cpp_lib_integer_sequence <= _MSVC_LANG) \ || (__cpp_lib_integer_sequence <= __cplusplus)) // Array initialization usin C++14 template std::array make_array( P&& i, std::index_sequence is) { return { (Ints == is.size() - 1 ? std::move(i) : i)...}; } template std::array make_array( P&& i) { return make_array

(std::move(i), std::make_index_sequence{}); } #else // C++11 fallback template std::array make_array( P&& i, Ts&&... args); template struct make_array_choice { template static std::array res( P&& i, Ts&&... args) { P tmp(i); return make_array(std::move(i), std::move(tmp), std::move(args)...); } }; template struct make_array_choice { template static std::array res( P&& i, Ts&&... args) { return {std::move(i), std::move(args)...}; } }; template std::array make_array( P&& i, Ts&&... args) { return make_array_choice < N == (sizeof...(Ts) + 1), N, Ts ... > ::res(std::move(i), std::move(args)...); } #endif // defined(__cpp_lib_integer_sequence) } // namespace template< class Proxy, std::size_t N = 4> class ProxyPool { mutable std::mutex mtx_; std::condition_variable cv_; std::array heap_; std::bitset mask_; // unique_ptr deleters class D { // Because ProxyPool will be destroy after all the proxies are returned // this reference is always valid ProxyPool& pool_; friend class ProxyPool; D( ProxyPool* pool) : pool_(*pool) { } public: void operator ()( Proxy* p) const { pool_.set_back(p); } } deleter_; friend class D; /* * Return an available proxy to the pool. * @param p pointer to the proxy. */ void set_back( Proxy* p) noexcept { std::size_t idx = p - heap_.data(); std::lock_guard _(mtx_); // check is not there assert(!mask_.test(idx)); // return the resource mask_.set(idx); // notify the resource is free cv_.notify_one(); } public: using smart_ptr = std::unique_ptr; /* * Constructor of the pool object. * @param init Initialization value for all the proxies. */ ProxyPool( Proxy&& init) : heap_(make_array(std::move(init))) , deleter_(this) { // make all resources available mask_.set(); } /* * Destructor for the pool object. * It waits till all the proxies are back in the pool to prevent data races. */ ~ProxyPool() { std::unique_lock lock(mtx_); cv_.wait(lock, [&]() { return mask_.all(); }); } /* * Returns the number of proxies in the pool. * @return pool size */ static constexpr std::size_t size() { return N; } /* * Returns the number of proxies available in the pool. * @return available proxies */ std::size_t available() const noexcept { std::lock_guard _(mtx_); return mask_.count(); } /* * Retrieve an available proxy from the pool. * If not available a wait ensues. * Note deleter is referenced not copied to avoid heap allocations on smart pointer construction * @return unique_ptr referencing the proxy. On destruction the resource is returned. */ std::unique_ptr get() { std::unique_lock lock(mtx_); // wait for available resources cv_.wait(lock, [&]() { return mask_.any(); }); // find the first available std::size_t idx = 0; while (idx < mask_.size() && !mask_.test(idx)) { ++idx; } // retrieve it mask_.reset(idx); return std::unique_ptr(&heap_[idx], deleter_); } }; } // eprosima namespace #endif /* FASTRTPS_UTILS_PROXY_POOL_HPP_ */