source: finroc_plugins_data_ports/common/tPortBufferPool.h @ 137:a51ce184f4f2

17.03
Last change on this file since 137:a51ce184f4f2 was 137:a51ce184f4f2, checked in by Max Reichardt <max.reichardt@…>, 12 months ago

Merge with 17.03

File size: 8.6 KB
Line 
1//
2// You received this file as part of Finroc
3// A framework for intelligent robot control
4//
5// Copyright (C) Finroc GbR (finroc.org)
6//
7// This program is free software; you can redistribute it and/or modify
8// it under the terms of the GNU General Public License as published by
9// the Free Software Foundation; either version 2 of the License, or
10// (at your option) any later version.
11//
12// This program is distributed in the hope that it will be useful,
13// but WITHOUT ANY WARRANTY; without even the implied warranty of
14// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15// GNU General Public License for more details.
16//
17// You should have received a copy of the GNU General Public License along
18// with this program; if not, write to the Free Software Foundation, Inc.,
19// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20//
21//----------------------------------------------------------------------
22/*!\file    plugins/data_ports/common/tPortBufferPool.h
23 *
24 * \author  Max Reichardt
25 *
26 * \date    2012-10-30
27 *
28 * \brief   Contains tPortBufferPool
29 *
30 * \b tPortBufferPool
31 *
32 * Pool of buffers used in ports - for a specific data type.
33 *
34 */
35//----------------------------------------------------------------------
36#ifndef __plugins__data_ports__common__tPortBufferPool_h__
37#define __plugins__data_ports__common__tPortBufferPool_h__
38
39//----------------------------------------------------------------------
40// External includes (system with <>, local with "")
41//----------------------------------------------------------------------
42#include "rrlib/buffer_pools/tBufferPool.h"
43#include "rrlib/rtti/rtti.h"
44#include "core/definitions.h"
45#include "core/internal/tGarbageDeleter.h"
46
47//----------------------------------------------------------------------
48// Internal includes with ""
49//----------------------------------------------------------------------
50#include "plugins/data_ports/common/tAbstractPortBufferManager.h"
51#include "plugins/data_ports/optimized/cheaply_copied_types.h"
52
53//----------------------------------------------------------------------
54// Namespace declaration
55//----------------------------------------------------------------------
56namespace finroc
57{
58namespace data_ports
59{
60
61//----------------------------------------------------------------------
62// Forward declarations / typedefs / enums
63//----------------------------------------------------------------------
64namespace standard
65{
66class tPortBufferManager;
67}
68
69namespace common
70{
71
72//----------------------------------------------------------------------
73// Class declaration
74//----------------------------------------------------------------------
75//! Port buffer pool
76/*!
77 * Pool of buffers used in ports - for a specific data type.
78 *
79 * In order to be real-time-capable, enough buffers need to be allocated initially...
80 * otherwise the application becomes real-time-capable later - after enough buffers
81 * have been allocated.
82 *
83 * \tparam TBufferManager Buffer manager type (derived from tAbstractPortBufferManager)
84 * \tparam CONCURRENCY specifies if threads can return (write) and retrieve (read) buffers from the pool concurrently.
85 */
86template <typename TBufferManager, rrlib::concurrent_containers::tConcurrency CONCURRENCY>
87class tPortBufferPool : private rrlib::util::tNoncopyable
88{
89
90  /*!
91   * As buffers (at least their management information (reference counter etc.))
92   * could be accessed by a thread while it is returned to possibly deleted pool -
93   * deleting of these buffers should happen when its safe.
94   * Therefore, this deleter passes them to tGarbageDeleter.
95   */
96  struct tPortBufferDeleter
97  {
98    void operator()(TBufferManager* p) const
99    {
100      core::internal::tGarbageDeleter::DeleteDeferred<TBufferManager>(p);
101    }
102  };
103
104  typedef rrlib::buffer_pools::tBufferPool < TBufferManager, CONCURRENCY, rrlib::buffer_pools::management::QueueBased,
105          rrlib::buffer_pools::deleting::ComplainOnMissingBuffers, rrlib::buffer_pools::recycling::UseOwnerStorageInBuffer,
106          tPortBufferDeleter > tBufferPoolSingleThreaded;
107
108  typedef rrlib::buffer_pools::tBufferPool < TBufferManager, CONCURRENCY, rrlib::buffer_pools::management::QueueBased,
109          rrlib::buffer_pools::deleting::CollectGarbage, rrlib::buffer_pools::recycling::UseOwnerStorageInBuffer,
110          tPortBufferDeleter > tBufferPoolConcurrent;
111
112  /*! Type of wrapped buffer pool */
113  typedef typename std::conditional < CONCURRENCY == rrlib::concurrent_containers::tConcurrency::NONE,
114          tBufferPoolSingleThreaded, tBufferPoolConcurrent >::type tBufferPool;
115
116  /*! Whether this is a buffer pool for a standard port */
117  enum { cSTANDARD_PORT = std::is_same<TBufferManager, standard::tPortBufferManager>::value };
118
119  /*! Information what kind of content buffers contain (either data type - or buffer size) */
120  typedef typename std::conditional<cSTANDARD_PORT, rrlib::rtti::tType, uint32_t>::type tContentId;
121
122//----------------------------------------------------------------------
123// Public methods and typedefs
124//----------------------------------------------------------------------
125public:
126
127  /*! std::unique_ptr returned by this class that will automatically recycle buffer when out of scope */
128  typedef typename tBufferPool::tPointer tPointer;
129
130  /*!
131   * \param buffer_content Buffer content
132   * \param intial_size Number of buffers to allocate initially
133   */
134  tPortBufferPool(const tContentId& buffer_content, int initial_size) :
135    buffer_pool()
136  {
137    AllocateAdditionalBuffers(buffer_content, std::max<size_t>(initial_size, tBufferPool::MinUnusedBuffersRequired()));
138  }
139
140  tPortBufferPool() : buffer_pool()
141  {}
142
143  /*!
144   * Allocates the specified number of additional buffers and adds them to pool
145   *
146   * \param buffer_content Buffer content
147   * \param count Number of buffers to allocate and add
148   */
149  inline void AllocateAdditionalBuffers(const tContentId& buffer_content, size_t count)
150  {
151    for (size_t i = 0; i < count; i++)
152    {
153      CreateBuffer(buffer_content);
154    }
155  }
156
157  /*!
158   * \param data_type Data type of desired buffer
159   * \param possibly_create_buffer Create new buffer if there is none in pool at the moment?
160   * \return Returns unused buffer. If there are no buffers that can be reused, a new buffer is allocated.
161   */
162  template <bool Tstandard_port = cSTANDARD_PORT>
163  inline tPointer GetUnusedBuffer(const typename std::enable_if<Tstandard_port, rrlib::rtti::tType>::type& data_type, bool possibly_create_buffer = true)
164  {
165    tPointer buffer = buffer_pool.GetUnusedBuffer();
166    if (buffer)
167    {
168      return std::move(buffer);
169    }
170    return possibly_create_buffer ? CreateBuffer(data_type) : tPointer();
171  }
172
173  /*!
174   * \param buffer_size Size of buffer
175   * \param data_type Data type of desired buffer
176   * \return Returns unused buffer. If there are no buffers that can be reused, a new buffer is allocated.
177   */
178  template <bool Tstandard_port = cSTANDARD_PORT>
179  inline tPointer GetUnusedBuffer(typename std::enable_if < !Tstandard_port, uint32_t >::type buffer_size, const rrlib::rtti::tType& data_type)
180  {
181    tPointer buffer = buffer_pool.GetUnusedBuffer();
182    if (buffer)
183    {
184      return std::move(buffer);
185    }
186    return CreateBuffer(buffer_size);
187  }
188
189  /*!
190   * \return Returns internal buffer management backend for special manual tweaking of buffer pool.
191   */
192  typename tBufferPool::tBufferManagement& InternalBufferManagement()
193  {
194    return buffer_pool.InternalBufferManagement();
195  }
196
197//----------------------------------------------------------------------
198// Private fields and methods
199//----------------------------------------------------------------------
200private:
201
202  /*! Wrapped buffer pool */
203  tBufferPool buffer_pool;
204
205
206  /*
207   * \param buffer_content Buffer content
208   * \return Create new buffer/instance of port data and add to pool
209   */
210  tPointer CreateBuffer(const tContentId& buffer_content)
211  {
212    std::unique_ptr<TBufferManager> new_buffer(TBufferManager::CreateInstance(buffer_content));
213
214    // In case we have a string: allocate a certain buffer size (for RT capabilities with smaller payload) -
215    // We do not need this check for 'cheaply copied' types - therefore the concurrency condition
216    if (cSTANDARD_PORT && new_buffer->GetObject().GetType().GetRttiName() == typeid(tString).name())
217    {
218      static_cast<rrlib::rtti::tGenericObject&>(new_buffer->GetObject()).GetData<tString>().reserve(512);  // TODO: move to parameter in some config.h
219    }
220    return buffer_pool.AddBuffer(std::move(new_buffer));
221  }
222};
223
224//----------------------------------------------------------------------
225// End of namespace declaration
226//----------------------------------------------------------------------
227}
228}
229}
230
231#endif
Note: See TracBrowser for help on using the repository browser.