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