GNU Octave
3.8.0
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
Main Page
Namespaces
Classes
Files
File List
File Members
All
Classes
Namespaces
Files
Functions
Variables
Typedefs
Enumerations
Enumerator
Properties
Friends
Macros
Pages
liboctave
util
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>
34
class
octave_local_buffer
35
{
36
public
:
37
octave_local_buffer
(
size_t
size
)
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!
50
octave_local_buffer
(
const
octave_local_buffer
&);
51
octave_local_buffer
&
operator =
(
const
octave_local_buffer
&);
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
67
class
octave_chunk_buffer
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
124
SPECIALIZE_POD_BUFFER
(
bool
);
125
SPECIALIZE_POD_BUFFER
(
char
);
126
SPECIALIZE_POD_BUFFER
(
unsigned
short
);
127
SPECIALIZE_POD_BUFFER
(
short
);
128
SPECIALIZE_POD_BUFFER
(
int
);
129
SPECIALIZE_POD_BUFFER
(
unsigned
int
);
130
SPECIALIZE_POD_BUFFER
(
long
);
131
SPECIALIZE_POD_BUFFER
(
unsigned
long
);
132
SPECIALIZE_POD_BUFFER
(
float
);
133
SPECIALIZE_POD_BUFFER
(
double
);
134
// FIXME: Are these guaranteed to be POD and satisfy alignment?
135
SPECIALIZE_POD_BUFFER
(
Complex
);
136
SPECIALIZE_POD_BUFFER
(
FloatComplex
);
137
// MORE ?
138
139
// All pointers and const pointers are also POD types.
140
template
<
class
T>
141
class
octave_local_buffer
<T *> :
private
octave_chunk_buffer
142
{
143
public
:
144
octave_local_buffer
(
size_t
size
)
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
:
155
octave_local_buffer
(
size_t
size
)
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
Generated on Mon Dec 30 2013 03:04:54 for GNU Octave by
1.8.1.2