Moved stack unit test to gtest framework
[libcds.git] / cds / opt / buffer.h
1 /*
2     This file is a part of libcds - Concurrent Data Structures library
3
4     (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2016
5
6     Source code repo: http://github.com/khizmax/libcds/
7     Download: http://sourceforge.net/projects/libcds/files/
8     
9     Redistribution and use in source and binary forms, with or without
10     modification, are permitted provided that the following conditions are met:
11
12     * Redistributions of source code must retain the above copyright notice, this
13       list of conditions and the following disclaimer.
14
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.
18
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.     
29 */
30
31 #ifndef CDSLIB_OPT_BUFFER_H
32 #define CDSLIB_OPT_BUFFER_H
33
34 #include <cds/details/defs.h>
35 #include <cds/user_setup/allocator.h>
36 #include <cds/details/allocator.h>
37 #include <cds/algo/int_algo.h>
38
39 namespace cds { namespace opt {
40
41     /// [type-option] Option setter for user-provided plain buffer
42     /**
43         This option is used by some container as a random access array for storing
44         container's item; for example, a bounded queue may use
45         this option to define underlying buffer implementation.
46
47         The template parameter \p Type should be rebindable.
48
49         Implementations:
50             - \p opt::v::static_buffer
51             - \p opt::v::dynamic_buffer
52     */
53     template <typename Type>
54     struct buffer {
55         //@cond
56         template <typename Base> struct pack: public Base
57         {
58             typedef Type buffer;
59         };
60         //@endcond
61     };
62
63     namespace v {
64
65         /// Static buffer
66         /**
67             One of available type for \p opt::buffer option.
68
69             This buffer maintains static array. No dynamic memory allocation performed.
70
71             \par Template parameters:
72                 - \p T - item type the buffer stores
73                 - \p Capacity - the capacity of buffer. The value must be power of two if \p Exp2 is \p true
74                 - \p Exp2 - a boolean flag. If it is \p true the buffer capacity must be power of two.
75                     Otherwise it can be any positive number. Usually, it is required that the buffer has
76                     size of a power of two.
77         */
78         template <typename T, size_t Capacity, bool Exp2 = true>
79         class static_buffer
80         {
81         public:
82             typedef T   value_type  ;   ///< value type
83             static CDS_CONSTEXPR const size_t c_nCapacity = Capacity ;    ///< Capacity
84             static CDS_CONSTEXPR const bool c_bExp2 = Exp2; ///< \p Exp2 flag
85
86             /// Rebind buffer for other template parameters
87             template <typename Q, size_t Capacity2 = c_nCapacity, bool Exp22 = c_bExp2>
88             struct rebind {
89                 typedef static_buffer<Q, Capacity2, Exp22> other   ;   ///< Rebind result type
90             };
91
92             // Capacity must be power of 2
93             static_assert(!c_bExp2 || (c_nCapacity & (c_nCapacity - 1)) == 0, "Capacity must be power of two");
94
95         private:
96             //@cond
97             value_type  m_buffer[c_nCapacity];
98             //@endcond
99         public:
100             /// Construct static buffer
101             static_buffer() CDS_NOEXCEPT
102             {}
103             /// Construct buffer of given capacity
104             /**
105                 This ctor ignores \p nCapacity argument. The capacity of static buffer
106                 is defined by template argument \p Capacity
107             */
108             static_buffer( size_t nCapacity ) CDS_NOEXCEPT
109             {
110                 CDS_UNUSED( nCapacity );
111             }
112
113             static_buffer( const static_buffer& ) = delete;
114             static_buffer& operator =( const static_buffer& ) = delete;
115
116             /// Get item \p i
117             value_type& operator []( size_t i )
118             {
119                 assert( i < capacity() );
120                 return m_buffer[i];
121             }
122
123             /// Get item \p i, const version
124             const value_type& operator []( size_t i ) const
125             {
126                 assert( i < capacity() );
127                 return m_buffer[i];
128             }
129
130             /// Returns buffer capacity
131             CDS_CONSTEXPR size_t capacity() const CDS_NOEXCEPT
132             {
133                 return c_nCapacity;
134             }
135
136             /// Zeroize the buffer
137             void zeroize()
138             {
139                 memset( m_buffer, 0, capacity() * sizeof(m_buffer[0]) );
140             }
141
142             /// Returns pointer to buffer array
143             value_type * buffer() CDS_NOEXCEPT
144             {
145                 return m_buffer;
146             }
147
148             /// Returns pointer to buffer array
149             value_type * buffer() const CDS_NOEXCEPT
150             {
151                 return m_buffer;
152             }
153         };
154
155
156         /// Dynamically allocated buffer
157         /**
158             One of available type for \p opt::buffer option.
159
160             This buffer maintains dynamically allocated array.
161             Allocation is performed at construction time.
162
163             \par Template parameters:
164                 - \p T - item type storing in the buffer
165                 - \p Alloc - an allocator used for allocating internal buffer (\p std::allocator interface)
166                 - \p Exp2 - a boolean flag. If it is \p true the buffer capacity must be power of two.
167                     Otherwise it can be any positive number. Usually, it is required that the buffer has
168                     size of a power of two.
169         */
170         template <typename T, class Alloc = CDS_DEFAULT_ALLOCATOR, bool Exp2 = true>
171         class dynamic_buffer
172         {
173         public:
174             typedef T   value_type  ;   ///< Value type
175             static CDS_CONSTEXPR const bool c_bExp2 = Exp2; ///< \p Exp2 flag
176
177             /// Rebind buffer for other template parameters
178             template <typename Q, typename Alloc2=Alloc, bool Exp22 = c_bExp2>
179             struct rebind {
180                 typedef dynamic_buffer<Q, Alloc2, Exp22> other   ;  ///< Rebinding result type
181             };
182
183             //@cond
184             typedef cds::details::Allocator<value_type, Alloc>   allocator_type;
185             //@endcond
186
187         private:
188             //@cond
189             value_type *    m_buffer;
190             size_t const    m_nCapacity;
191             //@endcond
192         public:
193             /// Allocates dynamic buffer of given \p nCapacity
194             /**
195                 If \p Exp2 class template parameter is \p true then actual capacity
196                 of allocating buffer is nearest upper to \p nCapacity power of two.
197             */
198             dynamic_buffer( size_t nCapacity )
199                 : m_nCapacity( c_bExp2 ? beans::ceil2(nCapacity) : nCapacity )
200             {
201                 assert( m_nCapacity >= 2 );
202                 // Capacity must be power of 2
203                 assert( !c_bExp2 || (m_nCapacity & (m_nCapacity - 1)) == 0 );
204
205                 allocator_type a;
206                 m_buffer = a.NewArray( m_nCapacity );
207             }
208
209             /// Destroys dynamically allocated buffer
210             ~dynamic_buffer()
211             {
212                 allocator_type a;
213                 a.Delete( m_buffer, m_nCapacity );
214             }
215
216             dynamic_buffer( const dynamic_buffer& ) = delete;
217             dynamic_buffer& operator =( const dynamic_buffer& ) = delete;
218
219             /// Get item \p i
220             value_type& operator []( size_t i )
221             {
222                 assert( i < capacity() );
223                 return m_buffer[i];
224             }
225
226             /// Get item \p i, const version
227             const value_type& operator []( size_t i ) const
228             {
229                 assert( i < capacity() );
230                 return m_buffer[i];
231             }
232
233             /// Returns buffer capacity
234             size_t capacity() const CDS_NOEXCEPT
235             {
236                 return m_nCapacity;
237             }
238
239             /// Zeroize the buffer
240             void zeroize()
241             {
242                 memset( m_buffer, 0, capacity() * sizeof(m_buffer[0]) );
243             }
244
245             /// Returns pointer to buffer array
246             value_type * buffer() CDS_NOEXCEPT
247             {
248                 return m_buffer;
249             }
250
251             /// Returns pointer to buffer array
252             value_type * buffer() const CDS_NOEXCEPT
253             {
254                 return m_buffer;
255             }
256         };
257
258     }   // namespace v
259
260 }}  // namespace cds::opt
261
262 #endif // #ifndef CDSLIB_OPT_BUFFER_H