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