GNU Octave  3.8.0
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
oct-locbuf.h
Go to the documentation of this file.
1 /*
2 
3 Copyright (C) 2008-2013 Jaroslav Hajek
4 
5 This file is part of Octave.
6 
7 Octave is free software; you can redistribute it and/or modify it
8 under the terms of the GNU General Public License as published by the
9 Free Software Foundation; either version 3 of the License, or (at your
10 option) any later version.
11 
12 Octave is distributed in the hope that it will be useful, but WITHOUT
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 for more details.
16 
17 You should have received a copy of the GNU General Public License
18 along with Octave; see the file COPYING. If not, see
19 <http://www.gnu.org/licenses/>.
20 
21 */
22 
23 #if !defined (octave_oct_locbuf_h)
24 #define octave_oct_locbuf_h 1
25 
26 #include <cstddef>
27 #include "oct-cmplx.h"
28 
29 // The default local buffer simply encapsulates an *array* pointer
30 // that gets deleted automatically. For common POD types, we provide
31 // specializations.
32 
33 template <class T>
35 {
36 public:
38  : data (0)
39  {
40  if (size)
41  data = new T [size];
42  }
43  ~octave_local_buffer (void) { delete [] data; }
44  operator T *() const { return data; }
45 
46 private:
47  T *data;
48 
49  // No copying!
52 };
53 
54 // For buffers of POD types, we'll be smarter. There is one thing
55 // that differentiates a local buffer from a dynamic array - the local
56 // buffers, if not manipulated improperly, have a FIFO semantics,
57 // meaning that if buffer B is allocated after buffer A, B *must* be
58 // deallocated before A. This is *guaranteed* if you use local buffer
59 // exclusively through the OCTAVE_LOCAL_BUFFER macro, because the C++
60 // standard requires that explicit local objects be destroyed in
61 // reverse order of declaration. Therefore, we can avoid memory
62 // fragmentation by allocating fairly large chunks of memory and
63 // serving local buffers from them in a stack-like manner. The first
64 // returning buffer in previous chunk will be responsible for
65 // deallocating the chunk.
66 
68 {
69 public:
70 
71  OCTAVE_API octave_chunk_buffer (size_t size);
72 
73  OCTAVE_API virtual ~octave_chunk_buffer (void);
74 
75  char *data (void) const { return dat; }
76 
77  static OCTAVE_API void clear (void);
78 
79 private:
80 
81  // The number of bytes we allocate for each large chunk of memory we
82  // manage.
83  static const size_t chunk_size;
84 
85  // Pointer to the end end of the last allocation.
86  static char *top;
87 
88  // Pointer to the current active chunk.
89  static char *chunk;
90 
91  // The number of bytes remaining in the active chunk.
92  static size_t left;
93 
94  // The number of active allocations.
95  static size_t active;
96 
97  // Pointer to the current chunk.
98  char *cnk;
99 
100  // Pointer to the beginning of the most recent allocation.
101  char *dat;
102 
103  // No copying!
104  octave_chunk_buffer (const octave_chunk_buffer&);
105  octave_chunk_buffer& operator = (const octave_chunk_buffer&);
106 };
107 
108 // This specializes octave_local_buffer to use the chunked buffer
109 // mechanism for POD types.
110 #define SPECIALIZE_POD_BUFFER(TYPE) \
111 template <> \
112 class octave_local_buffer<TYPE> : private octave_chunk_buffer \
113 { \
114 public: \
115  octave_local_buffer (size_t size) \
116  : octave_chunk_buffer (size * sizeof (TYPE)) { } \
117  \
118  operator TYPE *() const \
119  { \
120  return reinterpret_cast<TYPE *> (this->data ()); \
121  } \
122 }
123 
126 SPECIALIZE_POD_BUFFER (unsigned short);
129 SPECIALIZE_POD_BUFFER (unsigned int);
131 SPECIALIZE_POD_BUFFER (unsigned long);
134 // FIXME: Are these guaranteed to be POD and satisfy alignment?
137 // MORE ?
138 
139 // All pointers and const pointers are also POD types.
140 template <class T>
142 {
143 public:
145  : octave_chunk_buffer (size * sizeof (T *))
146  { }
147 
148  operator T **() const { return reinterpret_cast<T **> (this->data ()); }
149 };
150 
151 template <class T>
152 class octave_local_buffer<const T *> : private octave_chunk_buffer
153 {
154 public:
156  : octave_chunk_buffer (size * sizeof (const T *))
157  { }
158 
159  operator const T **() const
160  {
161  return reinterpret_cast<const T **> (this->data ());
162  }
163 };
164 
165 // If the compiler supports dynamic stack arrays, we can use the
166 // attached hack to place small buffer arrays on the stack. It may be
167 // even faster than our obstack-like optimization, but is dangerous
168 // because stack is a very limited resource, so we disable it.
169 
170 #if 0 // defined (HAVE_DYNAMIC_AUTO_ARRAYS)
171 
172 // Maximum buffer size (in bytes) to be placed on the stack.
173 
174 #define OCTAVE_LOCAL_BUFFER_MAX_STACK_SIZE 8192
175 
176 // If we have automatic arrays, we use an automatic array if the size
177 // is small enough. To avoid possibly evaluating 'size' multiple
178 // times, we first cache it. Note that we always construct both the
179 // stack array and the octave_local_buffer object, but only one of
180 // them will be nonempty.
181 
182 #define OCTAVE_LOCAL_BUFFER(T, buf, size) \
183  const size_t _bufsize_ ## buf = size; \
184  const bool _lbufaut_ ## buf = _bufsize_ ## buf * sizeof (T) \
185  <= OCTAVE_LOCAL_BUFFER_MAX_STACK_SIZE; \
186  T _bufaut_ ## buf [_lbufaut_ ## buf ? _bufsize_ ## buf : 0]; \
187  octave_local_buffer<T> _bufheap_ ## buf \
188  (!_lbufaut_ ## buf ? _bufsize_ ## buf : 0); \
189  T *buf = _lbufaut_ ## buf \
190  ? _bufaut_ ## buf : static_cast<T *> (_bufheap_ ## buf)
191 
192 #else
193 
194 // If we don't have automatic arrays, we simply always use
195 // octave_local_buffer.
196 
197 #define OCTAVE_LOCAL_BUFFER(T, buf, size) \
198  octave_local_buffer<T> _buffer_ ## buf (size); \
199  T *buf = _buffer_ ## buf
200 
201 #endif
202 
203 // Note: we use weird variables in the for loop to avoid warnings
204 // about shadowed parameters.
205 
206 #define OCTAVE_LOCAL_BUFFER_INIT(T, buf, size, value) \
207  OCTAVE_LOCAL_BUFFER (T, buf, size); \
208  for (size_t _buf_iter = 0, _buf_size = size; \
209  _buf_iter < _buf_size; _buf_iter++) \
210  buf[_buf_iter] = value
211 
212 #endif
213