2 This file is a part of libcds - Concurrent Data Structures library
4 (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2017
6 Source code repo: http://github.com/khizmax/libcds/
7 Download: http://sourceforge.net/projects/libcds/files/
9 Redistribution and use in source and binary forms, with or without
10 modification, are permitted provided that the following conditions are met:
12 * Redistributions of source code must retain the above copyright notice, this
13 list of conditions and the following disclaimer.
15 * Redistributions in binary form must reproduce the above copyright notice,
16 this list of conditions and the following disclaimer in the documentation
17 and/or other materials provided with the distribution.
19 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
23 FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25 SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
26 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
27 OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 #ifndef CDSLIB_OPT_BUFFER_H
32 #define CDSLIB_OPT_BUFFER_H
35 #include <cds/details/defs.h>
36 #include <cds/user_setup/allocator.h>
37 #include <cds/details/allocator.h>
38 #include <cds/algo/int_algo.h>
40 namespace cds { namespace opt {
42 /// [type-option] Option setter for user-provided plain buffer
44 This option is used by some container as a random access array for storing
45 container's item; for example, a bounded queue may use
46 this option to define underlying buffer implementation.
48 The template parameter \p Type should be rebindable.
51 - \p opt::v::initialized_static_buffer
52 - \p opt::v::uninitialized_static_buffer
53 - \p opt::v::initialized_dynamic_buffer
54 - \p opt::v::uninitialized_dynamic_buffer
56 Uninitialized buffer is just an array of uninitialized elements.
57 Each element should be manually constructed, for example with a placement new operator.
58 When the uninitialized buffer is destroyed the destructor of its element is not called.
60 Initialized buffer contains default-constructed elements. Element destructor is called automatically
61 when the buffer is destroyed.
63 @note Usually, initialized and uninitialized buffers are not interchangeable.
65 template <typename Type>
68 template <typename Base> struct pack: public Base
77 /// Static uninitialized buffer
79 One of available type for \p opt::buffer option.
81 This buffer maintains static array of uninitialized elements.
82 You should manually construct each element when needed.
83 No dynamic memory allocation performed.
85 \par Template parameters:
86 - \p T - item type the buffer stores
87 - \p Capacity - the capacity of buffer. The value must be power of two if \p Exp2 is \p true
88 - \p Exp2 - a boolean flag. If it is \p true the buffer capacity must be power of two.
89 Otherwise it can be any positive number. Usually, it is required that the buffer has
90 size of a power of two.
92 template <typename T, size_t Capacity, bool Exp2 = true>
93 class uninitialized_static_buffer
96 typedef T value_type; ///< value type
97 static CDS_CONSTEXPR const size_t c_nCapacity = Capacity; ///< Capacity
98 static CDS_CONSTEXPR const bool c_bExp2 = Exp2; ///< \p Exp2 flag
100 /// Rebind buffer for other template parameters
101 template <typename Q, size_t Capacity2 = c_nCapacity, bool Exp22 = c_bExp2>
103 typedef uninitialized_static_buffer<Q, Capacity2, Exp22> other; ///< Rebind result type
106 // Capacity must be power of 2
107 static_assert(!c_bExp2 || (c_nCapacity & (c_nCapacity - 1)) == 0, "Capacity must be power of two");
119 element m_buffer[c_nCapacity];
122 /// Construct static buffer
123 uninitialized_static_buffer() CDS_NOEXCEPT
126 /// Construct buffer of given capacity
128 This ctor ignores \p nCapacity argument. The capacity of static buffer
129 is defined by template argument \p Capacity
131 uninitialized_static_buffer( size_t nCapacity ) CDS_NOEXCEPT
133 CDS_UNUSED( nCapacity );
136 uninitialized_static_buffer( const uninitialized_static_buffer& ) = delete;
137 uninitialized_static_buffer& operator =( const uninitialized_static_buffer& ) = delete;
140 value_type& operator []( size_t i )
142 assert( i < capacity());
143 return m_buffer[i].v;
146 /// Get item \p i, const version
147 const value_type& operator []( size_t i ) const
149 assert( i < capacity());
150 return m_buffer[i].v;
153 /// Returns buffer capacity
154 CDS_CONSTEXPR size_t capacity() const CDS_NOEXCEPT
159 /// Zeroize the buffer
162 memset( m_buffer, 0, capacity() * sizeof(m_buffer[0]));
165 /// Returns pointer to buffer array
166 value_type * buffer() CDS_NOEXCEPT
168 return &( m_buffer[0].v );
171 /// Returns pointer to buffer array
172 value_type * buffer() const CDS_NOEXCEPT
174 return &( m_buffer[0].v );
177 /// Returns <tt> idx % capacity() </tt>
179 If the buffer size is a power of two, binary arithmethics is used
180 instead of modulo arithmetics
182 size_t mod( size_t idx )
185 return idx & ( capacity() - 1 );
187 return idx % capacity();
191 /// Static initialized buffer
193 One of available type for \p opt::buffer option.
195 This buffer maintains static array of default-constructed elements.
196 No dynamic memory allocation performed.
198 \par Template parameters:
199 - \p T - item type the buffer stores
200 - \p Capacity - the capacity of buffer. The value must be power of two if \p Exp2 is \p true
201 - \p Exp2 - a boolean flag. If it is \p true the buffer capacity must be power of two.
202 Otherwise it can be any positive number. Usually, it is required that the buffer has
203 size of a power of two.
205 template <typename T, size_t Capacity, bool Exp2 = true>
206 class initialized_static_buffer
209 typedef T value_type; ///< value type
210 static CDS_CONSTEXPR const size_t c_nCapacity = Capacity; ///< Capacity
211 static CDS_CONSTEXPR const bool c_bExp2 = Exp2; ///< \p Exp2 flag
213 /// Rebind buffer for other template parameters
214 template <typename Q, size_t Capacity2 = c_nCapacity, bool Exp22 = c_bExp2>
216 typedef initialized_static_buffer<Q, Capacity2, Exp22> other; ///< Rebind result type
219 // Capacity must be power of 2
220 static_assert(!c_bExp2 || (c_nCapacity & (c_nCapacity - 1)) == 0, "Capacity must be power of two");
224 value_type m_buffer[c_nCapacity];
227 /// Construct static buffer
228 initialized_static_buffer() CDS_NOEXCEPT
231 /// Construct buffer of given capacity
233 This ctor ignores \p nCapacity argument. The capacity of static buffer
234 is defined by template argument \p Capacity
236 initialized_static_buffer( size_t nCapacity ) CDS_NOEXCEPT
238 CDS_UNUSED( nCapacity );
241 initialized_static_buffer( const initialized_static_buffer& ) = delete;
242 initialized_static_buffer& operator =( const initialized_static_buffer& ) = delete;
245 value_type& operator []( size_t i )
247 assert( i < capacity());
251 /// Get item \p i, const version
252 const value_type& operator []( size_t i ) const
254 assert( i < capacity());
258 /// Returns buffer capacity
259 CDS_CONSTEXPR size_t capacity() const CDS_NOEXCEPT
264 /// Zeroize the buffer
267 memset( m_buffer, 0, capacity() * sizeof(m_buffer[0]));
270 /// Returns pointer to buffer array
271 value_type * buffer() CDS_NOEXCEPT
276 /// Returns pointer to buffer array
277 value_type * buffer() const CDS_NOEXCEPT
282 /// Returns <tt> idx % capacity() </tt>
284 If the buffer size is a power of two, binary arithmethics is used
285 instead of modulo arithmetics
287 size_t mod( size_t idx )
290 return idx & ( capacity() - 1 );
292 return idx % capacity();
296 /// Dynamically allocated uninitialized buffer
298 One of available type for \p opt::buffer option.
300 This buffer maintains dynamically allocated array of uninitialized elements.
301 You should manually construct each element when needed.
302 Allocation is performed at construction time.
304 \par Template parameters:
305 - \p T - item type storing in the buffer
306 - \p Alloc - an allocator used for allocating internal buffer (\p std::allocator interface)
307 - \p Exp2 - a boolean flag. If it is \p true the buffer capacity must be power of two.
308 Otherwise it can be any positive number. Usually, it is required that the buffer has
309 size of a power of two.
311 template <typename T, class Alloc = CDS_DEFAULT_ALLOCATOR, bool Exp2 = true>
312 class uninitialized_dynamic_buffer
315 typedef T value_type; ///< Value type
316 typedef Alloc allocator; ///< Allocator type;
317 static CDS_CONSTEXPR const bool c_bExp2 = Exp2; ///< \p Exp2 flag
319 /// Rebind buffer for other template parameters
320 template <typename Q, typename Alloc2= allocator, bool Exp22 = c_bExp2>
322 typedef uninitialized_dynamic_buffer<Q, Alloc2, Exp22> other; ///< Rebinding result type
326 typedef typename allocator::template rebind<value_type>::other allocator_type;
331 value_type * m_buffer;
332 size_t const m_nCapacity;
335 /// Allocates dynamic buffer of given \p nCapacity
337 If \p Exp2 class template parameter is \p true then actual capacity
338 of allocating buffer is nearest upper to \p nCapacity power of two.
340 uninitialized_dynamic_buffer( size_t nCapacity )
341 : m_nCapacity( c_bExp2 ? beans::ceil2(nCapacity) : nCapacity )
343 assert( m_nCapacity >= 2 );
344 // Capacity must be power of 2
345 assert( !c_bExp2 || (m_nCapacity & (m_nCapacity - 1)) == 0 );
347 m_buffer = allocator_type().allocate( m_nCapacity );
350 /// Destroys dynamically allocated buffer
351 ~uninitialized_dynamic_buffer()
353 allocator_type().deallocate( m_buffer, m_nCapacity );
356 uninitialized_dynamic_buffer( const uninitialized_dynamic_buffer& ) = delete;
357 uninitialized_dynamic_buffer& operator =( const uninitialized_dynamic_buffer& ) = delete;
360 value_type& operator []( size_t i )
362 assert( i < capacity());
366 /// Get item \p i, const version
367 const value_type& operator []( size_t i ) const
369 assert( i < capacity());
373 /// Returns buffer capacity
374 size_t capacity() const CDS_NOEXCEPT
379 /// Zeroize the buffer
382 memset( m_buffer, 0, capacity() * sizeof(m_buffer[0]));
385 /// Returns pointer to buffer array
386 value_type * buffer() CDS_NOEXCEPT
391 /// Returns pointer to buffer array
392 value_type * buffer() const CDS_NOEXCEPT
397 /// Returns <tt> idx % capacity() </tt>
399 If the buffer size is a power of two, binary arithmethics is used
400 instead of modulo arithmetics
402 size_t mod( size_t idx )
404 static_if ( c_bExp2 )
405 return idx & ( capacity() - 1 );
407 return idx % capacity();
412 /// Dynamically allocated initialized buffer
414 One of available type for \p opt::buffer option.
416 This buffer maintains dynamically allocated array of initialized default-constructed elements.
417 Allocation is performed at construction time.
419 \par Template parameters:
420 - \p T - item type storing in the buffer
421 - \p Alloc - an allocator used for allocating internal buffer (\p std::allocator interface)
422 - \p Exp2 - a boolean flag. If it is \p true the buffer capacity must be power of two.
423 Otherwise it can be any positive number. Usually, it is required that the buffer has
424 size of a power of two.
426 template <typename T, class Alloc = CDS_DEFAULT_ALLOCATOR, bool Exp2 = true>
427 class initialized_dynamic_buffer
430 typedef T value_type; ///< Value type
431 typedef Alloc allocator; ///< Allocator type
432 static CDS_CONSTEXPR const bool c_bExp2 = Exp2; ///< \p Exp2 flag
434 /// Rebind buffer for other template parameters
435 template <typename Q, typename Alloc2= allocator, bool Exp22 = c_bExp2>
437 typedef initialized_dynamic_buffer<Q, Alloc2, Exp22> other; ///< Rebinding result type
441 typedef cds::details::Allocator<value_type, allocator> allocator_type;
446 value_type * m_buffer;
447 size_t const m_nCapacity;
450 /// Allocates dynamic buffer of given \p nCapacity
452 If \p Exp2 class template parameter is \p true then actual capacity
453 of allocating buffer is nearest upper to \p nCapacity power of two.
455 initialized_dynamic_buffer( size_t nCapacity )
456 : m_nCapacity( c_bExp2 ? beans::ceil2(nCapacity) : nCapacity )
458 assert( m_nCapacity >= 2 );
459 // Capacity must be power of 2
460 assert( !c_bExp2 || (m_nCapacity & (m_nCapacity - 1)) == 0 );
463 m_buffer = a.NewArray( m_nCapacity );
466 /// Destroys dynamically allocated buffer
467 ~initialized_dynamic_buffer()
470 a.Delete( m_buffer, m_nCapacity );
473 initialized_dynamic_buffer( const initialized_dynamic_buffer& ) = delete;
474 initialized_dynamic_buffer& operator =( const initialized_dynamic_buffer& ) = delete;
477 value_type& operator []( size_t i )
479 assert( i < capacity());
483 /// Get item \p i, const version
484 const value_type& operator []( size_t i ) const
486 assert( i < capacity());
490 /// Returns buffer capacity
491 size_t capacity() const CDS_NOEXCEPT
496 /// Zeroize the buffer
499 memset( m_buffer, 0, capacity() * sizeof(m_buffer[0]));
502 /// Returns pointer to buffer array
503 value_type * buffer() CDS_NOEXCEPT
508 /// Returns pointer to buffer array
509 value_type * buffer() const CDS_NOEXCEPT
514 /// Returns <tt> idx % capacity() </tt>
516 If the buffer size is a power of two, binary arithmethics is used
517 instead of modulo arithmetics
519 size_t mod( size_t idx )
522 return idx & ( capacity() - 1 );
524 return idx % capacity();
530 }} // namespace cds::opt
532 #endif // #ifndef CDSLIB_OPT_BUFFER_H