+ /// Dynamically allocated uninitialized buffer
+ /**
+ One of available type for \p opt::buffer option.
+
+ This buffer maintains dynamically allocated array of uninitialized elements.
+ You should manually construct each element when needed.
+ Allocation is performed at construction time.
+
+ \par Template parameters:
+ - \p T - item type storing in the buffer
+ - \p Alloc - an allocator used for allocating internal buffer (\p std::allocator interface)
+ - \p Exp2 - a boolean flag. If it is \p true the buffer capacity must be power of two.
+ Otherwise it can be any positive number. Usually, it is required that the buffer has
+ size of a power of two.
+ */
+ template <typename T, class Alloc = CDS_DEFAULT_ALLOCATOR, bool Exp2 = true>
+ class uninitialized_dynamic_buffer
+ {
+ public:
+ typedef T value_type; ///< Value type
+ static CDS_CONSTEXPR const bool c_bExp2 = Exp2; ///< \p Exp2 flag
+
+ /// Rebind buffer for other template parameters
+ template <typename Q, typename Alloc2=Alloc, bool Exp22 = c_bExp2>
+ struct rebind {
+ typedef uninitialized_dynamic_buffer<Q, Alloc2, Exp22> other; ///< Rebinding result type
+ };
+
+ //@cond
+ typedef typename Alloc::template rebind<value_type>::other allocator_type;
+ //@endcond
+
+ private:
+ //@cond
+ value_type * m_buffer;
+ size_t const m_nCapacity;
+ //@endcond
+ public:
+ /// Allocates dynamic buffer of given \p nCapacity
+ /**
+ If \p Exp2 class template parameter is \p true then actual capacity
+ of allocating buffer is nearest upper to \p nCapacity power of two.
+ */
+ uninitialized_dynamic_buffer( size_t nCapacity )
+ : m_nCapacity( c_bExp2 ? beans::ceil2(nCapacity) : nCapacity )
+ {
+ assert( m_nCapacity >= 2 );
+ // Capacity must be power of 2
+ assert( !c_bExp2 || (m_nCapacity & (m_nCapacity - 1)) == 0 );
+
+ m_buffer = allocator_type().allocate( m_nCapacity );
+ }
+
+ /// Destroys dynamically allocated buffer
+ ~uninitialized_dynamic_buffer()
+ {
+ allocator_type().deallocate( m_buffer, m_nCapacity );
+ }
+
+ uninitialized_dynamic_buffer( const uninitialized_dynamic_buffer& ) = delete;
+ uninitialized_dynamic_buffer& operator =( const uninitialized_dynamic_buffer& ) = delete;
+
+ /// Get item \p i
+ value_type& operator []( size_t i )
+ {
+ assert( i < capacity() );
+ return m_buffer[i];
+ }
+
+ /// Get item \p i, const version
+ const value_type& operator []( size_t i ) const
+ {
+ assert( i < capacity() );
+ return m_buffer[i];
+ }
+
+ /// Returns buffer capacity
+ size_t capacity() const CDS_NOEXCEPT
+ {
+ return m_nCapacity;
+ }
+
+ /// Zeroize the buffer
+ void zeroize()
+ {
+ memset( m_buffer, 0, capacity() * sizeof(m_buffer[0]) );
+ }
+
+ /// Returns pointer to buffer array
+ value_type * buffer() CDS_NOEXCEPT
+ {
+ return m_buffer;
+ }
+
+ /// Returns pointer to buffer array
+ value_type * buffer() const CDS_NOEXCEPT
+ {
+ return m_buffer;
+ }
+ };
+