BufferManager.hpp 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203
  1. ///
  2. /// \file Framework/BufferManager.hpp
  3. ///
  4. /// BufferManager provides an output pool of buffers.
  5. ///
  6. /// \copyright
  7. /// Copyright (c) 2013-2017 Josh Blum
  8. /// 2020 Nicholas Corgan
  9. /// SPDX-License-Identifier: BSL-1.0
  10. ///
  11. #pragma once
  12. #include <Pothos/Config.hpp>
  13. #include <Pothos/Framework/ManagedBuffer.hpp>
  14. #include <Pothos/Framework/BufferChunk.hpp>
  15. #include <memory> //shared_ptr
  16. #include <string>
  17. #include <functional>
  18. namespace Pothos {
  19. /*!
  20. * BufferManagerArgs - constructor arguments for BufferManager.
  21. */
  22. struct POTHOS_API BufferManagerArgs
  23. {
  24. BufferManagerArgs(void);
  25. /*!
  26. * The number of managed buffers available from the manager.
  27. * Buffers are checked into and out of the manager frequently.
  28. * A small number of buffers are needed to allow for parallelism,
  29. * so buffers can be checked out while other buffers are in use.
  30. * Default: 4 buffers
  31. */
  32. size_t numBuffers;
  33. /*!
  34. * The number of bytes available per each managed buffer.
  35. * Default: 8 kibibytes
  36. */
  37. size_t bufferSize;
  38. /*!
  39. * The NUMA node affinity for the generic slab allocator.
  40. * This argument is not used for the special-case managers.
  41. * Default: -1 or unspecified affinity
  42. */
  43. long nodeAffinity;
  44. };
  45. /*!
  46. * A BufferManager has a queue-like interface to manage buffers.
  47. * Since buffers can represent special DMA memory,
  48. * the buffer manager is responsible for DMA hooks.
  49. */
  50. class POTHOS_API BufferManager
  51. {
  52. public:
  53. typedef std::shared_ptr<BufferManager> Sptr;
  54. using AllocateFcn = std::function<SharedBuffer(const BufferManagerArgs& args)>;
  55. //! Virtual destructor for derived buffer managers
  56. virtual ~BufferManager(void);
  57. /*!
  58. * The BufferManager factory -- makes a new BufferManager given the factory name.
  59. * This factory call does not invoke init() on the buffer manager.
  60. * Plugins for custom BufferManagers should be located in
  61. * the plugin registry: /framework/buffer_manager/[name]
  62. * \throws BufferManagerFactoryError if the factory function fails.
  63. * \param name the name of a BufferManager factory in the plugin tree
  64. * \return a new shared pointer to a buffer manager
  65. */
  66. static Sptr make(const std::string &name);
  67. /*!
  68. * The BufferManager factory -- makes a new BufferManager given the factory name.
  69. * Plugins for custom BufferManagers should be located in
  70. * the plugin registry: /framework/buffer_manager/[name]
  71. * \throws BufferManagerFactoryError if the factory function fails.
  72. * \param name the name of a BufferManager factory in the plugin tree
  73. * \param args the buffer manager init arguments
  74. * \return a new shared pointer to a buffer manager
  75. */
  76. static Sptr make(const std::string &name, const BufferManagerArgs &args);
  77. /*!
  78. * The BufferManager factory -- makes a new BufferManager given the factory name.
  79. * Plugins for custom BufferManagers should be located in
  80. * the plugin registry: /framework/buffer_manager/[name]
  81. * \throws BufferManagerFactoryError if the factory function fails.
  82. * \param name the name of a BufferManager factory in the plugin tree
  83. * \param args the buffer manager init arguments
  84. * \param allocateFcn a custom function allocate memory
  85. * \return a new shared pointer to a buffer manager
  86. */
  87. static Sptr make(const std::string &name, const BufferManagerArgs &args, const AllocateFcn &allocateFcn);
  88. /*!
  89. * Init is called once at factory time to initialize the buffers.
  90. */
  91. virtual void init(const BufferManagerArgs &args);
  92. /*!
  93. * Is the manager empty?
  94. * \return true if no buffers are available
  95. */
  96. virtual bool empty(void) const = 0;
  97. /*!
  98. * Get a reference to the front buffer.
  99. * front().address will be the start of a valid buffer,
  100. * front().length will be the number of bytes available.
  101. * The caller sets length to indicate bytes used.
  102. * \return the buffer at the queue head
  103. */
  104. const BufferChunk &front(void) const;
  105. /*!
  106. * Pop bytes from the front buffer.
  107. * This operation removes available bytes from the manager.
  108. * Calling pop removes a managed buffer from an internal queue;
  109. * the bytes removed are only restored to the manager via push.
  110. *
  111. * If this manager is responsible for DMA writes,
  112. * the pop operation should cause a write operation.
  113. * If this manager is responsible for DMA reads,
  114. * this pop operation should cause a read operation.
  115. *
  116. * \param numBytes the number of bytes to remove
  117. */
  118. virtual void pop(const size_t numBytes) = 0;
  119. /*!
  120. * Push returns a buffer to the manager.
  121. * The buffer may be available via a call to front()
  122. * depending upon the implementation of the manager.
  123. * \throw BufferPushError if buffer does not belong to this manager.
  124. * \param buff the buffer to return
  125. */
  126. virtual void push(const ManagedBuffer &buff) = 0;
  127. /*!
  128. * Push external returns a buffer to the manager through a callback.
  129. * This call is used to return a buffer from a different thread context.
  130. * The callback implements the thread-safe delivery mechanism.
  131. */
  132. void pushExternal(const ManagedBuffer &buff);
  133. /*!
  134. * Specify a custom function that takes in a BufferManagerArgs instance
  135. * and returns a SharedBuffer to be managed.
  136. */
  137. void setAllocateFunction(const AllocateFcn &allocateFcn);
  138. /*!
  139. * Set the callback for use with the pushExternal API call.
  140. */
  141. void setCallback(const std::function<void(const ManagedBuffer &)> &callback);
  142. //! Has this buffer manager been initialized?
  143. bool isInitialized(void) const;
  144. protected:
  145. //! Default constructor
  146. BufferManager(void);
  147. //! Called by derived classes to set the buffer for front()
  148. void setFrontBuffer(const BufferChunk &buff);
  149. AllocateFcn _allocateFcn;
  150. private:
  151. bool _initialized;
  152. BufferChunk _frontBuffer;
  153. std::function<void(const ManagedBuffer &)> _callback;
  154. };
  155. } //namespace Pothos
  156. inline const Pothos::BufferChunk &Pothos::BufferManager::front(void) const
  157. {
  158. return _frontBuffer;
  159. }
  160. inline void Pothos::BufferManager::setFrontBuffer(const BufferChunk &buff)
  161. {
  162. _frontBuffer = buff;
  163. }
  164. inline void Pothos::BufferManager::pushExternal(const ManagedBuffer &buff)
  165. {
  166. if (_callback) _callback(buff);
  167. else this->push(buff);
  168. }
  169. inline bool Pothos::BufferManager::isInitialized(void) const
  170. {
  171. return _initialized;
  172. }