123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287 |
- ///
- /// \file Framework/ManagedBuffer.hpp
- ///
- /// A ManagedBuffer is checked-out and automatically returned to a BufferManager.
- ///
- /// \copyright
- /// Copyright (c) 2013-2017 Josh Blum
- /// 2019 Nicholas Corgan
- /// SPDX-License-Identifier: BSL-1.0
- ///
- #pragma once
- #include <Pothos/Config.hpp>
- #include <Pothos/Framework/SharedBuffer.hpp>
- #include <memory> //shared_ptr
- #include <atomic>
- #include <cassert>
- namespace Pothos {
- //! Forward declares
- class BufferManager;
- class BufferChunk;
- class BufferAccumulator;
- /*!
- * A ManagedBuffer is a buffer that interacts with a BufferManager.
- * The ManagedBuffer maintains a reference count, and when no more
- * copies are held by the user, the ManagedBuffer will be returned
- * to the BufferManager; unless the BufferManager has been deleted.
- */
- class POTHOS_API ManagedBuffer
- {
- public:
- /*!
- * Create a null buffer.
- * All fields are initialized to zero.
- */
- ManagedBuffer(void);
- /*!
- * Create from a shared buffer with no manager.
- */
- ManagedBuffer(const SharedBuffer &buff);
- /*!
- * Is this managed buffer valid?
- * \return true if it holds an allocation.
- */
- explicit operator bool(void) const;
- /*!
- * Reset any reference held by the managed buffer.
- * This managed buffer will become a null buffer.
- */
- void reset(void);
- /*!
- * Reset the managed buffer for its next usage.
- * \param manager shared pointer to the buffer manager
- * \param buff the shared buffer with memory and length
- * \param slabIndex an identifying index used with slabs
- */
- void reset(std::shared_ptr<BufferManager> manager, const SharedBuffer &buff, const size_t slabIndex = 0);
- /*!
- * Get the internal buffer as set by the manager
- * and which cannot be changed by the caller.
- * \return a const reference to the buffer
- */
- const SharedBuffer &getBuffer(void) const;
- /*!
- * Get the slab index associated with this buffer.
- * The slab index related to implementation specifics.
- * Typically, this index is only used when the underlying
- * buffer is sourced from a continuous slab of memory.
- */
- size_t getSlabIndex(void) const;
- //! ManagedBuffer destructor
- ~ManagedBuffer(void);
- //! ManagedBuffer copy constructor
- ManagedBuffer(const ManagedBuffer &obj);
- //! ManagedBuffer move constructor
- ManagedBuffer(ManagedBuffer &&obj) noexcept;
- //! ManagedBuffer copy assignment
- ManagedBuffer &operator=(const ManagedBuffer &obj);
- //! ManagedBuffer move assignment
- ManagedBuffer &operator=(ManagedBuffer &&obj);
- //! Get the associated buffer manager
- std::shared_ptr<BufferManager> getBufferManager(void) const;
- //! sortable operator for ManagedBuffer
- bool operator<(const ManagedBuffer &) const;
- /*!
- * Is the reference to the managed buffer unique?
- * \return true if this is the only copy of the managed buffer
- */
- bool unique(void) const;
- /*!
- * The number of copies of the managed buffer.
- */
- size_t useCount(void) const;
- /*!
- * Set the next contiguous buffer in the chain.
- */
- void setNextBuffer(const ManagedBuffer &next);
- /*!
- * Get the next contiguous buffer in the chain.
- * Or return a null managed buffer if there is none.
- */
- ManagedBuffer getNextBuffer(void) const;
- private:
- friend BufferChunk;
- friend BufferAccumulator;
- struct Impl; Impl *_impl;
- ManagedBuffer(Impl *impl);
- POTHOS_API friend bool operator==(const ManagedBuffer &lhs, const ManagedBuffer &rhs);
- POTHOS_API friend bool operator!=(const ManagedBuffer &lhs, const ManagedBuffer &rhs);
- };
- /*!
- * Equality operator for ManagedBuffer.
- * True when the containers are identical.
- */
- inline bool operator==(const ManagedBuffer &lhs, const ManagedBuffer &rhs);
- /*!
- * Inquality operator for ManagedBuffer.
- * True when the containers are not identical.
- */
- inline bool operator!=(const ManagedBuffer &lhs, const ManagedBuffer &rhs);
- } //namespace Pothos
- struct Pothos::ManagedBuffer::Impl
- {
- Impl(void);
- std::atomic<int> counter;
- std::weak_ptr<BufferManager> weakManager;
- SharedBuffer buffer;
- size_t slabIndex;
- Pothos::ManagedBuffer::Impl *nextBuffer;
- void incr(void)
- {
- counter.fetch_add(1, std::memory_order_relaxed);
- }
- void decr(void)
- {
- //decrement the counter, and handle the last ref case
- if (counter.fetch_sub(1, std::memory_order_release) == 1)
- {
- std::atomic_thread_fence(std::memory_order_acquire);
- this->cleanup();
- }
- }
- void cleanup(void);
- };
- inline Pothos::ManagedBuffer::ManagedBuffer(void):
- _impl(nullptr)
- {
- return;
- }
- inline Pothos::ManagedBuffer::operator bool(void) const
- {
- return _impl != nullptr;
- }
- inline void Pothos::ManagedBuffer::reset(void)
- {
- if (_impl != nullptr) _impl->decr();
- _impl = nullptr;
- }
- inline const Pothos::SharedBuffer &Pothos::ManagedBuffer::getBuffer(void) const
- {
- if (_impl == nullptr) return SharedBuffer::null();
- return _impl->buffer;
- }
- inline size_t Pothos::ManagedBuffer::getSlabIndex(void) const
- {
- assert(*this);
- return _impl->slabIndex;
- }
- inline Pothos::ManagedBuffer::~ManagedBuffer(void)
- {
- if (_impl != nullptr) _impl->decr();
- }
- inline Pothos::ManagedBuffer::ManagedBuffer(const ManagedBuffer &obj):
- _impl(obj._impl)
- {
- if (_impl != nullptr) _impl->incr();
- }
- inline Pothos::ManagedBuffer::ManagedBuffer(ManagedBuffer &&obj) noexcept:
- _impl(obj._impl)
- {
- obj._impl = nullptr;
- }
- inline Pothos::ManagedBuffer &Pothos::ManagedBuffer::operator=(const ManagedBuffer &obj)
- {
- if (_impl != nullptr) _impl->decr();
- this->_impl = obj._impl;
- if (_impl != nullptr) _impl->incr();
- return *this;
- }
- inline Pothos::ManagedBuffer &Pothos::ManagedBuffer::operator=(ManagedBuffer &&obj)
- {
- if (_impl != nullptr) _impl->decr();
- this->_impl = obj._impl;
- obj._impl = nullptr;
- return *this;
- }
- inline std::shared_ptr<Pothos::BufferManager> Pothos::ManagedBuffer::getBufferManager(void) const
- {
- assert(*this);
- return _impl->weakManager.lock();
- }
- inline bool Pothos::ManagedBuffer::operator<(const ManagedBuffer &rhs) const
- {
- return _impl < rhs._impl;
- }
- inline bool Pothos::ManagedBuffer::unique(void) const
- {
- if (_impl == nullptr) return false;
- return _impl->counter.load(std::memory_order_relaxed) == 1;
- }
- inline size_t Pothos::ManagedBuffer::useCount(void) const
- {
- if (_impl == nullptr) return 0;
- return _impl->counter.load(std::memory_order_relaxed);
- }
- inline void Pothos::ManagedBuffer::setNextBuffer(const ManagedBuffer &next)
- {
- assert(*this);
- _impl->nextBuffer = next._impl;
- }
- inline Pothos::ManagedBuffer Pothos::ManagedBuffer::getNextBuffer(void) const
- {
- assert(*this);
- return Pothos::ManagedBuffer(_impl->nextBuffer);
- }
- inline Pothos::ManagedBuffer::ManagedBuffer(Impl *impl):
- _impl(impl)
- {
- if (_impl != nullptr) _impl->incr();
- }
- inline bool Pothos::operator==(const ManagedBuffer &lhs, const ManagedBuffer &rhs)
- {
- return lhs._impl == rhs._impl;
- }
- inline bool Pothos::operator!=(const ManagedBuffer &lhs, const ManagedBuffer &rhs)
- {
- return !(lhs == rhs);
- }
|