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 Initialized and uninitialized buffers are not
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 static CDS_CONSTEXPR const bool c_bExp2 = Exp2; ///< \p Exp2 flag
292 /// Rebind buffer for other template parameters
293 template <typename Q, typename Alloc2=Alloc, bool Exp22 = c_bExp2>
295 typedef uninitialized_dynamic_buffer<Q, Alloc2, Exp22> other; ///< Rebinding result type
299 typedef typename Alloc::template rebind<value_type>::other allocator_type;
304 value_type * m_buffer;
305 size_t const m_nCapacity;
308 /// Allocates dynamic buffer of given \p nCapacity
310 If \p Exp2 class template parameter is \p true then actual capacity
311 of allocating buffer is nearest upper to \p nCapacity power of two.
313 uninitialized_dynamic_buffer( size_t nCapacity )
314 : m_nCapacity( c_bExp2 ? beans::ceil2(nCapacity) : nCapacity )
316 assert( m_nCapacity >= 2 );
317 // Capacity must be power of 2
318 assert( !c_bExp2 || (m_nCapacity & (m_nCapacity - 1)) == 0 );
320 m_buffer = allocator_type().allocate( m_nCapacity );
323 /// Destroys dynamically allocated buffer
324 ~uninitialized_dynamic_buffer()
326 allocator_type().deallocate( m_buffer, m_nCapacity );
329 uninitialized_dynamic_buffer( const uninitialized_dynamic_buffer& ) = delete;
330 uninitialized_dynamic_buffer& operator =( const uninitialized_dynamic_buffer& ) = delete;
333 value_type& operator []( size_t i )
335 assert( i < capacity() );
339 /// Get item \p i, const version
340 const value_type& operator []( size_t i ) const
342 assert( i < capacity() );
346 /// Returns buffer capacity
347 size_t capacity() const CDS_NOEXCEPT
352 /// Zeroize the buffer
355 memset( m_buffer, 0, capacity() * sizeof(m_buffer[0]) );
358 /// Returns pointer to buffer array
359 value_type * buffer() CDS_NOEXCEPT
364 /// Returns pointer to buffer array
365 value_type * buffer() const CDS_NOEXCEPT
372 /// Dynamically allocated initialized buffer
374 One of available type for \p opt::buffer option.
376 This buffer maintains dynamically allocated array of initialized default-constructed elements.
377 Allocation is performed at construction time.
379 \par Template parameters:
380 - \p T - item type storing in the buffer
381 - \p Alloc - an allocator used for allocating internal buffer (\p std::allocator interface)
382 - \p Exp2 - a boolean flag. If it is \p true the buffer capacity must be power of two.
383 Otherwise it can be any positive number. Usually, it is required that the buffer has
384 size of a power of two.
386 template <typename T, class Alloc = CDS_DEFAULT_ALLOCATOR, bool Exp2 = true>
387 class initialized_dynamic_buffer
390 typedef T value_type; ///< Value type
391 static CDS_CONSTEXPR const bool c_bExp2 = Exp2; ///< \p Exp2 flag
393 /// Rebind buffer for other template parameters
394 template <typename Q, typename Alloc2=Alloc, bool Exp22 = c_bExp2>
396 typedef initialized_dynamic_buffer<Q, Alloc2, Exp22> other; ///< Rebinding result type
400 typedef cds::details::Allocator<value_type, Alloc> allocator_type;
405 value_type * m_buffer;
406 size_t const m_nCapacity;
409 /// Allocates dynamic buffer of given \p nCapacity
411 If \p Exp2 class template parameter is \p true then actual capacity
412 of allocating buffer is nearest upper to \p nCapacity power of two.
414 initialized_dynamic_buffer( size_t nCapacity )
415 : m_nCapacity( c_bExp2 ? beans::ceil2(nCapacity) : nCapacity )
417 assert( m_nCapacity >= 2 );
418 // Capacity must be power of 2
419 assert( !c_bExp2 || (m_nCapacity & (m_nCapacity - 1)) == 0 );
422 m_buffer = a.NewArray( m_nCapacity );
425 /// Destroys dynamically allocated buffer
426 ~initialized_dynamic_buffer()
429 a.Delete( m_buffer, m_nCapacity );
432 initialized_dynamic_buffer( const initialized_dynamic_buffer& ) = delete;
433 initialized_dynamic_buffer& operator =( const initialized_dynamic_buffer& ) = delete;
436 value_type& operator []( size_t i )
438 assert( i < capacity() );
442 /// Get item \p i, const version
443 const value_type& operator []( size_t i ) const
445 assert( i < capacity() );
449 /// Returns buffer capacity
450 size_t capacity() const CDS_NOEXCEPT
455 /// Zeroize the buffer
458 memset( m_buffer, 0, capacity() * sizeof(m_buffer[0]) );
461 /// Returns pointer to buffer array
462 value_type * buffer() CDS_NOEXCEPT
467 /// Returns pointer to buffer array
468 value_type * buffer() const CDS_NOEXCEPT
476 }} // namespace cds::opt
478 #endif // #ifndef CDSLIB_OPT_BUFFER_H