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