2 This file is a part of libcds - Concurrent Data Structures library
4 (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2016
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 );
178 /// Static initialized buffer
180 One of available type for \p opt::buffer option.
182 This buffer maintains static array of default-constructed elements.
183 No dynamic memory allocation performed.
185 \par Template parameters:
186 - \p T - item type the buffer stores
187 - \p Capacity - the capacity of buffer. The value must be power of two if \p Exp2 is \p true
188 - \p Exp2 - a boolean flag. If it is \p true the buffer capacity must be power of two.
189 Otherwise it can be any positive number. Usually, it is required that the buffer has
190 size of a power of two.
192 template <typename T, size_t Capacity, bool Exp2 = true>
193 class initialized_static_buffer
196 typedef T value_type; ///< value type
197 static CDS_CONSTEXPR const size_t c_nCapacity = Capacity; ///< Capacity
198 static CDS_CONSTEXPR const bool c_bExp2 = Exp2; ///< \p Exp2 flag
200 /// Rebind buffer for other template parameters
201 template <typename Q, size_t Capacity2 = c_nCapacity, bool Exp22 = c_bExp2>
203 typedef initialized_static_buffer<Q, Capacity2, Exp22> other; ///< Rebind result type
206 // Capacity must be power of 2
207 static_assert(!c_bExp2 || (c_nCapacity & (c_nCapacity - 1)) == 0, "Capacity must be power of two");
211 value_type m_buffer[c_nCapacity];
214 /// Construct static buffer
215 initialized_static_buffer() CDS_NOEXCEPT
218 /// Construct buffer of given capacity
220 This ctor ignores \p nCapacity argument. The capacity of static buffer
221 is defined by template argument \p Capacity
223 initialized_static_buffer( size_t nCapacity ) CDS_NOEXCEPT
225 CDS_UNUSED( nCapacity );
228 initialized_static_buffer( const initialized_static_buffer& ) = delete;
229 initialized_static_buffer& operator =( const initialized_static_buffer& ) = delete;
232 value_type& operator []( size_t i )
234 assert( i < capacity() );
238 /// Get item \p i, const version
239 const value_type& operator []( size_t i ) const
241 assert( i < capacity() );
245 /// Returns buffer capacity
246 CDS_CONSTEXPR size_t capacity() const CDS_NOEXCEPT
251 /// Zeroize the buffer
254 memset( m_buffer, 0, capacity() * sizeof(m_buffer[0]) );
257 /// Returns pointer to buffer array
258 value_type * buffer() CDS_NOEXCEPT
263 /// Returns pointer to buffer array
264 value_type * buffer() const CDS_NOEXCEPT
270 /// Dynamically allocated uninitialized buffer
272 One of available type for \p opt::buffer option.
274 This buffer maintains dynamically allocated array of uninitialized elements.
275 You should manually construct each element when needed.
276 Allocation is performed at construction time.
278 \par Template parameters:
279 - \p T - item type storing in the buffer
280 - \p Alloc - an allocator used for allocating internal buffer (\p std::allocator interface)
281 - \p Exp2 - a boolean flag. If it is \p true the buffer capacity must be power of two.
282 Otherwise it can be any positive number. Usually, it is required that the buffer has
283 size of a power of two.
285 template <typename T, class Alloc = CDS_DEFAULT_ALLOCATOR, bool Exp2 = true>
286 class uninitialized_dynamic_buffer
289 typedef T value_type; ///< Value type
290 typedef Alloc allocator; ///< Allocator type;
291 static CDS_CONSTEXPR const bool c_bExp2 = Exp2; ///< \p Exp2 flag
293 /// Rebind buffer for other template parameters
294 template <typename Q, typename Alloc2= allocator, bool Exp22 = c_bExp2>
296 typedef uninitialized_dynamic_buffer<Q, Alloc2, Exp22> other; ///< Rebinding result type
300 typedef typename allocator::template rebind<value_type>::other allocator_type;
305 value_type * m_buffer;
306 size_t const m_nCapacity;
309 /// Allocates dynamic buffer of given \p nCapacity
311 If \p Exp2 class template parameter is \p true then actual capacity
312 of allocating buffer is nearest upper to \p nCapacity power of two.
314 uninitialized_dynamic_buffer( size_t nCapacity )
315 : m_nCapacity( c_bExp2 ? beans::ceil2(nCapacity) : nCapacity )
317 assert( m_nCapacity >= 2 );
318 // Capacity must be power of 2
319 assert( !c_bExp2 || (m_nCapacity & (m_nCapacity - 1)) == 0 );
321 m_buffer = allocator_type().allocate( m_nCapacity );
324 /// Destroys dynamically allocated buffer
325 ~uninitialized_dynamic_buffer()
327 allocator_type().deallocate( m_buffer, m_nCapacity );
330 uninitialized_dynamic_buffer( const uninitialized_dynamic_buffer& ) = delete;
331 uninitialized_dynamic_buffer& operator =( const uninitialized_dynamic_buffer& ) = delete;
334 value_type& operator []( size_t i )
336 assert( i < capacity() );
340 /// Get item \p i, const version
341 const value_type& operator []( size_t i ) const
343 assert( i < capacity() );
347 /// Returns buffer capacity
348 size_t capacity() const CDS_NOEXCEPT
353 /// Zeroize the buffer
356 memset( m_buffer, 0, capacity() * sizeof(m_buffer[0]) );
359 /// Returns pointer to buffer array
360 value_type * buffer() CDS_NOEXCEPT
365 /// Returns pointer to buffer array
366 value_type * buffer() const CDS_NOEXCEPT
373 /// Dynamically allocated initialized buffer
375 One of available type for \p opt::buffer option.
377 This buffer maintains dynamically allocated array of initialized default-constructed elements.
378 Allocation is performed at construction time.
380 \par Template parameters:
381 - \p T - item type storing in the buffer
382 - \p Alloc - an allocator used for allocating internal buffer (\p std::allocator interface)
383 - \p Exp2 - a boolean flag. If it is \p true the buffer capacity must be power of two.
384 Otherwise it can be any positive number. Usually, it is required that the buffer has
385 size of a power of two.
387 template <typename T, class Alloc = CDS_DEFAULT_ALLOCATOR, bool Exp2 = true>
388 class initialized_dynamic_buffer
391 typedef T value_type; ///< Value type
392 typedef Alloc allocator; ///< Allocator type
393 static CDS_CONSTEXPR const bool c_bExp2 = Exp2; ///< \p Exp2 flag
395 /// Rebind buffer for other template parameters
396 template <typename Q, typename Alloc2= allocator, bool Exp22 = c_bExp2>
398 typedef initialized_dynamic_buffer<Q, Alloc2, Exp22> other; ///< Rebinding result type
402 typedef cds::details::Allocator<value_type, allocator> allocator_type;
407 value_type * m_buffer;
408 size_t const m_nCapacity;
411 /// Allocates dynamic buffer of given \p nCapacity
413 If \p Exp2 class template parameter is \p true then actual capacity
414 of allocating buffer is nearest upper to \p nCapacity power of two.
416 initialized_dynamic_buffer( size_t nCapacity )
417 : m_nCapacity( c_bExp2 ? beans::ceil2(nCapacity) : nCapacity )
419 assert( m_nCapacity >= 2 );
420 // Capacity must be power of 2
421 assert( !c_bExp2 || (m_nCapacity & (m_nCapacity - 1)) == 0 );
424 m_buffer = a.NewArray( m_nCapacity );
427 /// Destroys dynamically allocated buffer
428 ~initialized_dynamic_buffer()
431 a.Delete( m_buffer, m_nCapacity );
434 initialized_dynamic_buffer( const initialized_dynamic_buffer& ) = delete;
435 initialized_dynamic_buffer& operator =( const initialized_dynamic_buffer& ) = delete;
438 value_type& operator []( size_t i )
440 assert( i < capacity() );
444 /// Get item \p i, const version
445 const value_type& operator []( size_t i ) const
447 assert( i < capacity() );
451 /// Returns buffer capacity
452 size_t capacity() const CDS_NOEXCEPT
457 /// Zeroize the buffer
460 memset( m_buffer, 0, capacity() * sizeof(m_buffer[0]) );
463 /// Returns pointer to buffer array
464 value_type * buffer() CDS_NOEXCEPT
469 /// Returns pointer to buffer array
470 value_type * buffer() const CDS_NOEXCEPT
478 }} // namespace cds::opt
480 #endif // #ifndef CDSLIB_OPT_BUFFER_H