GNU Octave  4.2.1
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-2017 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 "octave-config.h"
27 
28 #include <cstddef>
29 #include "oct-cmplx.h"
30 
31 // The default local buffer simply encapsulates an *array* pointer
32 // that gets deleted automatically. For common POD types, we provide
33 // specializations.
34 
35 template <typename T>
37 {
38 public:
40  : data (0)
41  {
42  if (size)
43  data = new T [size];
44  }
45 
46  ~octave_local_buffer (void) { delete [] data; }
47 
48  operator T *() const { return data; }
49 
50 private:
51  T *data;
52 
53  // No copying!
56 };
57 
58 // For buffers of POD types, we'll be smarter. There is one thing
59 // that differentiates a local buffer from a dynamic array - the local
60 // buffers, if not manipulated improperly, have a FIFO semantics,
61 // meaning that if buffer B is allocated after buffer A, B *must* be
62 // deallocated before A. This is *guaranteed* if you use local buffer
63 // exclusively through the OCTAVE_LOCAL_BUFFER macro, because the C++
64 // standard requires that explicit local objects be destroyed in
65 // reverse order of declaration. Therefore, we can avoid memory
66 // fragmentation by allocating fairly large chunks of memory and
67 // serving local buffers from them in a stack-like manner. The first
68 // returning buffer in previous chunk will be responsible for
69 // deallocating the chunk.
70 
72 {
73 public:
74 
75  OCTAVE_API octave_chunk_buffer (size_t size);
76 
77  OCTAVE_API virtual ~octave_chunk_buffer (void);
78 
79  char *data (void) const { return dat; }
80 
81  static OCTAVE_API void clear (void);
82 
83 private:
84 
85  // The number of bytes we allocate for each large chunk of memory we
86  // manage.
87  static const size_t chunk_size;
88 
89  // Pointer to the end end of the last allocation.
90  static char *top;
91 
92  // Pointer to the current active chunk.
93  static char *chunk;
94 
95  // The number of bytes remaining in the active chunk.
96  static size_t left;
97 
98  // The number of active allocations.
99  static size_t active;
100 
101  // Pointer to the current chunk.
102  char *cnk;
103 
104  // Pointer to the beginning of the most recent allocation.
105  char *dat;
106 
107  // No copying!
108  octave_chunk_buffer (const octave_chunk_buffer&);
109  octave_chunk_buffer& operator = (const octave_chunk_buffer&);
110 };
111 
112 // This specializes octave_local_buffer to use the chunked buffer
113 // mechanism for POD types.
114 #define SPECIALIZE_POD_BUFFER(TYPE) \
115  template <> \
116  class octave_local_buffer<TYPE> : private octave_chunk_buffer \
117  { \
118  public: \
119  octave_local_buffer (size_t size) \
120  : octave_chunk_buffer (size * sizeof (TYPE)) { } \
121  \
122  operator TYPE *() const \
123  { \
124  return reinterpret_cast<TYPE *> (this->data ()); \
125  } \
126  }
127 
130 SPECIALIZE_POD_BUFFER (unsigned short);
133 SPECIALIZE_POD_BUFFER (unsigned int);
135 SPECIALIZE_POD_BUFFER (unsigned long);
138 // FIXME: Are these guaranteed to be POD and satisfy alignment?
141 // MORE ?
142 
143 // All pointers and const pointers are also POD types.
144 template <typename T>
146 {
147 public:
149  : octave_chunk_buffer (size * sizeof (T *))
150  { }
151 
152  operator T **() const { return reinterpret_cast<T **> (this->data ()); }
153 };
154 
155 template <typename T>
156 class octave_local_buffer<const T *> : private octave_chunk_buffer
157 {
158 public:
160  : octave_chunk_buffer (size * sizeof (const T *))
161  { }
162 
163  operator const T **() const
164  {
165  return reinterpret_cast<const T **> (this->data ());
166  }
167 };
168 
169 // If the compiler supports dynamic stack arrays, we can use the
170 // attached hack to place small buffer arrays on the stack. It may be
171 // even faster than our obstack-like optimization, but is dangerous
172 // because stack is a very limited resource, so we disable it.
173 
174 #if 0 // defined (HAVE_DYNAMIC_AUTO_ARRAYS)
175 
176 // Maximum buffer size (in bytes) to be placed on the stack.
177 
178 #define OCTAVE_LOCAL_BUFFER_MAX_STACK_SIZE 8192
179 
180 // If we have automatic arrays, we use an automatic array if the size
181 // is small enough. To avoid possibly evaluating 'size' multiple
182 // times, we first cache it. Note that we always construct both the
183 // stack array and the octave_local_buffer object, but only one of
184 // them will be nonempty.
185 
186 #define OCTAVE_LOCAL_BUFFER(T, buf, size) \
187  const size_t _bufsize_ ## buf = size; \
188  const bool _lbufaut_ ## buf = _bufsize_ ## buf * sizeof (T) \
189  <= OCTAVE_LOCAL_BUFFER_MAX_STACK_SIZE; \
190  T _bufaut_ ## buf [_lbufaut_ ## buf ? _bufsize_ ## buf : 0]; \
191  octave_local_buffer<T> _bufheap_ ## buf (! _lbufaut_ ## buf ? _bufsize_ ## buf : 0); \
192  T *buf = (_lbufaut_ ## buf \
193  ? _bufaut_ ## buf : static_cast<T *> (_bufheap_ ## buf))
194 
195 #else
196 
197 // If we don't have automatic arrays, we simply always use
198 // octave_local_buffer.
199 
200 #define OCTAVE_LOCAL_BUFFER(T, buf, size) \
201  octave_local_buffer<T> _buffer_ ## buf (size); \
202  T *buf = _buffer_ ## buf
203 
204 #endif
205 
206 // Note: we use weird variables in the for loop to avoid warnings
207 // about shadowed parameters.
208 
209 #define OCTAVE_LOCAL_BUFFER_INIT(T, buf, size, value) \
210  OCTAVE_LOCAL_BUFFER (T, buf, size); \
211  for (size_t _buf_iter = 0, _buf_size = size; \
212  _buf_iter < _buf_size; _buf_iter++) \
213  buf[_buf_iter] = value
214 
215 #endif
static char * chunk
Definition: oct-locbuf.h:93
static size_t active
Definition: oct-locbuf.h:99
octave_local_buffer(size_t size)
Definition: oct-locbuf.h:148
static char * top
Definition: oct-locbuf.h:90
static OCTAVE_API void clear(void)
Definition: oct-locbuf.cc:132
octave_local_buffer & operator=(const octave_local_buffer &)
static const size_t chunk_size
Definition: oct-locbuf.h:87
octave_local_buffer(size_t size)
Definition: oct-locbuf.h:39
octave_chunk_buffer & operator=(const octave_chunk_buffer &)
char * data(void) const
Definition: oct-locbuf.h:79
virtual OCTAVE_API ~octave_chunk_buffer(void)
Definition: oct-locbuf.cc:94
OCTAVE_API octave_chunk_buffer(size_t size)
Definition: oct-locbuf.cc:48
static size_t left
Definition: oct-locbuf.h:96
~octave_local_buffer(void)
Definition: oct-locbuf.h:46
std::complex< float > FloatComplex
Definition: oct-cmplx.h:32
OCTAVE_EXPORT octave_value_list any number nd example oindent prints the prompt xample Pick a any number!nd example oindent and waits for the user to enter a value The string entered by the user is evaluated as an so it may be a literal a variable or any other valid Octave code The number of return their size
Definition: input.cc:871
std::complex< double > Complex
Definition: oct-cmplx.h:31
#define SPECIALIZE_POD_BUFFER(TYPE)
Definition: oct-locbuf.h:114