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