SharedBuffer.hpp 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209
  1. ///
  2. /// \file Framework/SharedBuffer.hpp
  3. ///
  4. /// The shared buffer is an RAII buffer that automatically deallocates.
  5. ///
  6. /// \copyright
  7. /// Copyright (c) 2013-2017 Josh Blum
  8. /// 2019 Nicholas Corgan
  9. /// SPDX-License-Identifier: BSL-1.0
  10. ///
  11. #pragma once
  12. #include <Pothos/Config.hpp>
  13. #include <memory> //shared_ptr
  14. namespace Pothos {
  15. /*!
  16. * The SharedBuffer represents the combination of address and length,
  17. * and a shared pointer that will automatically cleanup the memory.
  18. */
  19. class POTHOS_API SharedBuffer
  20. {
  21. public:
  22. //! Get a const reference to a null/empty SharedBuffer
  23. static const SharedBuffer &null(void);
  24. //! Create a null SharedBuffer
  25. SharedBuffer(void);
  26. /*!
  27. * Create a SharedBuffer given a length in bytes.
  28. * This factory allocates memory which is held by the SharedBuffer.
  29. * When the SharedBuffer is deleted, the memory will be freed as well.
  30. * The node affinity is used to allocate physical memory on a NUMA node.
  31. *
  32. * \param numBytes the number of bytes to allocate in this buffer
  33. * \param nodeAffinity which NUMA node to allocate on (-1 for don't care)
  34. * \return a new shared buffer object
  35. */
  36. static SharedBuffer make(const size_t numBytes, const long nodeAffinity = -1);
  37. /*!
  38. * Create a circular SharedBuffer given a length in bytes.
  39. * The rules for the circular or double mapping are as follows:
  40. * for i in 0 to length-1: address + i == address + i + length
  41. *
  42. * This factory allocates memory which is held by the SharedBuffer.
  43. * When the SharedBuffer is deleted, the memory will be freed as well.
  44. * The node affinity is used to allocate physical memory on a NUMA node.
  45. *
  46. * \param numBytes the number of bytes to allocate in this buffer
  47. * \param nodeAffinity which NUMA node to allocate on (-1 for don't care)
  48. * \return a new circular shared buffer object
  49. */
  50. static SharedBuffer makeCirc(const size_t numBytes, const long nodeAffinity = -1);
  51. /*!
  52. * Create a SharedBuffer from address, length, and the container.
  53. * The container is any object that can be put into a shared_ptr.
  54. * When the shared pointer is deleted, the container's destructor
  55. * (written by the user) should handle the cleanup of the memory.
  56. */
  57. SharedBuffer(const size_t address, const size_t length, std::shared_ptr<void> container);
  58. /*!
  59. * Create a sub-buffer that is a subset of the buffer.
  60. * The shared container is copied so the sub-buffer holds a reference.
  61. * \throws SharedBufferError if the parameters would be out of bounds
  62. * \param address an address within the buffer
  63. * \param length the new length of the sub buffer
  64. * \param buffer a shared buffer which is a superset of this new one
  65. */
  66. SharedBuffer(const size_t address, const size_t length, const SharedBuffer &buffer);
  67. //! Get the address of the first byte of the buffer
  68. size_t getAddress(void) const;
  69. //! Get the length of the buffer in bytes
  70. size_t getLength(void) const;
  71. /*!
  72. * Get the alias address (non-zero for circular buffers).
  73. * Address and alias will point to the same physical memory.
  74. */
  75. size_t getAlias(void) const;
  76. /*!
  77. * Get the alias offset (non-zero for circular buffers).
  78. * Address and alias will point to the same physical memory.
  79. */
  80. size_t getAliasOffset(void) const;
  81. /*!
  82. * Set the alias address (non-zero for circular buffers).
  83. * Address and alias will point to the same physical memory.
  84. */
  85. void setAlias(const size_t alias);
  86. /*!
  87. * Get the end address - front address + length.
  88. * The end address is non-inclusive.
  89. * \return the end address
  90. */
  91. size_t getEnd(void) const;
  92. /*!
  93. * Is this instance of this shared buffer unique?
  94. * \return true if this is the only copy
  95. */
  96. bool unique(void) const;
  97. /*!
  98. * The number of copies of this shared buffer.
  99. */
  100. size_t useCount(void) const;
  101. /*!
  102. * Is this shared buffer valid?
  103. */
  104. explicit operator bool(void) const;
  105. /*!
  106. * Get access to the underlying memory container.
  107. */
  108. const std::shared_ptr<void> &getContainer(void) const;
  109. private:
  110. static SharedBuffer makeCircUnprotected(const size_t numBytes, const long nodeAffinity);
  111. size_t _address;
  112. size_t _length;
  113. size_t _alias;
  114. std::shared_ptr<void> _container;
  115. };
  116. /*!
  117. * Equality operator for SharedBuffer.
  118. * True when the containers are identical.
  119. */
  120. inline bool operator==(const SharedBuffer &lhs, const SharedBuffer &rhs);
  121. /*!
  122. * Inquality operator for SharedBuffer.
  123. * True when the containers are not identical.
  124. */
  125. inline bool operator!=(const SharedBuffer &lhs, const SharedBuffer &rhs);
  126. } //namespace Pothos
  127. inline size_t Pothos::SharedBuffer::getAddress(void) const
  128. {
  129. return _address;
  130. }
  131. inline size_t Pothos::SharedBuffer::getLength(void) const
  132. {
  133. return _length;
  134. }
  135. inline size_t Pothos::SharedBuffer::getAlias(void) const
  136. {
  137. return _alias;
  138. }
  139. inline size_t Pothos::SharedBuffer::getAliasOffset(void) const
  140. {
  141. return _alias ? _alias - _address : 0;
  142. }
  143. inline void Pothos::SharedBuffer::setAlias(const size_t alias)
  144. {
  145. _alias = alias;
  146. }
  147. inline size_t Pothos::SharedBuffer::getEnd(void) const
  148. {
  149. return _address + _length;
  150. }
  151. inline bool Pothos::SharedBuffer::unique(void) const
  152. {
  153. return _container.unique();
  154. }
  155. inline size_t Pothos::SharedBuffer::useCount(void) const
  156. {
  157. return _container.use_count();
  158. }
  159. inline Pothos::SharedBuffer::operator bool(void) const
  160. {
  161. return bool(_container);
  162. }
  163. inline const std::shared_ptr<void> &Pothos::SharedBuffer::getContainer(void) const
  164. {
  165. return _container;
  166. }
  167. inline bool Pothos::operator==(const SharedBuffer &lhs, const SharedBuffer &rhs)
  168. {
  169. return lhs.getContainer() == rhs.getContainer();
  170. }
  171. inline bool Pothos::operator!=(const SharedBuffer &lhs, const SharedBuffer &rhs)
  172. {
  173. return !(lhs == rhs);
  174. }