Mercurial > hg > octave-nkf
annotate liboctave/oct-locbuf.h @ 8400:7b6e1fc1cb90
implement obstack-like optimization of local buffers
author | Jaroslav Hajek <highegg@gmail.com> |
---|---|
date | Fri, 12 Dec 2008 12:45:31 +0100 |
parents | ad8ed668e0a4 |
children | f274fbc29747 |
rev | line source |
---|---|
8377 | 1 /* |
2 | |
3 Copyright (C) 2008 Jaroslav Hajek <highegg@gmail.com> | |
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_local_buffer_h) | |
24 #define octave_local_buffer_h 1 | |
25 | |
26 #include <cstddef> | |
8400
7b6e1fc1cb90
implement obstack-like optimization of local buffers
Jaroslav Hajek <highegg@gmail.com>
parents:
8379
diff
changeset
|
27 #include "oct-cmplx.h" |
8377 | 28 |
29 // The default local buffer simply encapsulates an *array* pointer that gets | |
30 // delete[]d automatically. For common POD types, we provide specializations. | |
31 | |
32 template <class T> | |
33 class octave_local_buffer | |
34 { | |
35 public: | |
36 octave_local_buffer (size_t size) | |
37 : data (0) | |
38 { | |
39 if (size) | |
40 data = new T[size]; | |
41 } | |
42 ~octave_local_buffer (void) { delete [] data; } | |
43 operator T *() const { return data; } | |
44 private: | |
45 T *data; | |
46 }; | |
47 | |
8400
7b6e1fc1cb90
implement obstack-like optimization of local buffers
Jaroslav Hajek <highegg@gmail.com>
parents:
8379
diff
changeset
|
48 // For buffers of POD types, we'll be more smart. There is one thing that |
7b6e1fc1cb90
implement obstack-like optimization of local buffers
Jaroslav Hajek <highegg@gmail.com>
parents:
8379
diff
changeset
|
49 // differentiates a local buffer from a dynamic array - the local buffers, if |
7b6e1fc1cb90
implement obstack-like optimization of local buffers
Jaroslav Hajek <highegg@gmail.com>
parents:
8379
diff
changeset
|
50 // not manipulated improperly, have a FIFO semantics, meaning that if buffer B |
7b6e1fc1cb90
implement obstack-like optimization of local buffers
Jaroslav Hajek <highegg@gmail.com>
parents:
8379
diff
changeset
|
51 // is allocated after buffer A, B *must* be deallocated before A. This is |
7b6e1fc1cb90
implement obstack-like optimization of local buffers
Jaroslav Hajek <highegg@gmail.com>
parents:
8379
diff
changeset
|
52 // *guaranteed* if you use local buffer exclusively through the |
7b6e1fc1cb90
implement obstack-like optimization of local buffers
Jaroslav Hajek <highegg@gmail.com>
parents:
8379
diff
changeset
|
53 // OCTAVE_LOCAL_BUFFER macro, because the C++ standard *mandates* explicit |
7b6e1fc1cb90
implement obstack-like optimization of local buffers
Jaroslav Hajek <highegg@gmail.com>
parents:
8379
diff
changeset
|
54 // local objects be destroyed in reverse order of declaration. |
7b6e1fc1cb90
implement obstack-like optimization of local buffers
Jaroslav Hajek <highegg@gmail.com>
parents:
8379
diff
changeset
|
55 // Therefore, we can avoid memory fragmentation by allocating fairly large |
7b6e1fc1cb90
implement obstack-like optimization of local buffers
Jaroslav Hajek <highegg@gmail.com>
parents:
8379
diff
changeset
|
56 // chunks of memory and serving local buffers from them in a stack-like manner. |
7b6e1fc1cb90
implement obstack-like optimization of local buffers
Jaroslav Hajek <highegg@gmail.com>
parents:
8379
diff
changeset
|
57 // The first returning buffer in previous chunk will be responsible for |
7b6e1fc1cb90
implement obstack-like optimization of local buffers
Jaroslav Hajek <highegg@gmail.com>
parents:
8379
diff
changeset
|
58 // deallocating the chunk. |
8377 | 59 |
8400
7b6e1fc1cb90
implement obstack-like optimization of local buffers
Jaroslav Hajek <highegg@gmail.com>
parents:
8379
diff
changeset
|
60 class octave_chunk_buffer |
7b6e1fc1cb90
implement obstack-like optimization of local buffers
Jaroslav Hajek <highegg@gmail.com>
parents:
8379
diff
changeset
|
61 { |
7b6e1fc1cb90
implement obstack-like optimization of local buffers
Jaroslav Hajek <highegg@gmail.com>
parents:
8379
diff
changeset
|
62 static const size_t chunk_size; |
7b6e1fc1cb90
implement obstack-like optimization of local buffers
Jaroslav Hajek <highegg@gmail.com>
parents:
8379
diff
changeset
|
63 |
7b6e1fc1cb90
implement obstack-like optimization of local buffers
Jaroslav Hajek <highegg@gmail.com>
parents:
8379
diff
changeset
|
64 static char *top, *chunk; |
7b6e1fc1cb90
implement obstack-like optimization of local buffers
Jaroslav Hajek <highegg@gmail.com>
parents:
8379
diff
changeset
|
65 static size_t left; |
7b6e1fc1cb90
implement obstack-like optimization of local buffers
Jaroslav Hajek <highegg@gmail.com>
parents:
8379
diff
changeset
|
66 |
7b6e1fc1cb90
implement obstack-like optimization of local buffers
Jaroslav Hajek <highegg@gmail.com>
parents:
8379
diff
changeset
|
67 char *cnk; |
7b6e1fc1cb90
implement obstack-like optimization of local buffers
Jaroslav Hajek <highegg@gmail.com>
parents:
8379
diff
changeset
|
68 char *dat; |
7b6e1fc1cb90
implement obstack-like optimization of local buffers
Jaroslav Hajek <highegg@gmail.com>
parents:
8379
diff
changeset
|
69 |
7b6e1fc1cb90
implement obstack-like optimization of local buffers
Jaroslav Hajek <highegg@gmail.com>
parents:
8379
diff
changeset
|
70 public: |
7b6e1fc1cb90
implement obstack-like optimization of local buffers
Jaroslav Hajek <highegg@gmail.com>
parents:
8379
diff
changeset
|
71 |
7b6e1fc1cb90
implement obstack-like optimization of local buffers
Jaroslav Hajek <highegg@gmail.com>
parents:
8379
diff
changeset
|
72 octave_chunk_buffer (size_t size); |
7b6e1fc1cb90
implement obstack-like optimization of local buffers
Jaroslav Hajek <highegg@gmail.com>
parents:
8379
diff
changeset
|
73 |
7b6e1fc1cb90
implement obstack-like optimization of local buffers
Jaroslav Hajek <highegg@gmail.com>
parents:
8379
diff
changeset
|
74 ~octave_chunk_buffer (void); |
7b6e1fc1cb90
implement obstack-like optimization of local buffers
Jaroslav Hajek <highegg@gmail.com>
parents:
8379
diff
changeset
|
75 |
7b6e1fc1cb90
implement obstack-like optimization of local buffers
Jaroslav Hajek <highegg@gmail.com>
parents:
8379
diff
changeset
|
76 char *data (void) const { return dat; } |
7b6e1fc1cb90
implement obstack-like optimization of local buffers
Jaroslav Hajek <highegg@gmail.com>
parents:
8379
diff
changeset
|
77 }; |
8377 | 78 |
8400
7b6e1fc1cb90
implement obstack-like optimization of local buffers
Jaroslav Hajek <highegg@gmail.com>
parents:
8379
diff
changeset
|
79 // This specializes octave_local_buffer to use the chunked buffer mechanism |
7b6e1fc1cb90
implement obstack-like optimization of local buffers
Jaroslav Hajek <highegg@gmail.com>
parents:
8379
diff
changeset
|
80 // for POD types. |
7b6e1fc1cb90
implement obstack-like optimization of local buffers
Jaroslav Hajek <highegg@gmail.com>
parents:
8379
diff
changeset
|
81 #define SPECIALIZE_POD_BUFFER(TYPE) \ |
7b6e1fc1cb90
implement obstack-like optimization of local buffers
Jaroslav Hajek <highegg@gmail.com>
parents:
8379
diff
changeset
|
82 template <> \ |
7b6e1fc1cb90
implement obstack-like optimization of local buffers
Jaroslav Hajek <highegg@gmail.com>
parents:
8379
diff
changeset
|
83 class octave_local_buffer<TYPE> : private octave_chunk_buffer \ |
7b6e1fc1cb90
implement obstack-like optimization of local buffers
Jaroslav Hajek <highegg@gmail.com>
parents:
8379
diff
changeset
|
84 { \ |
7b6e1fc1cb90
implement obstack-like optimization of local buffers
Jaroslav Hajek <highegg@gmail.com>
parents:
8379
diff
changeset
|
85 public: \ |
7b6e1fc1cb90
implement obstack-like optimization of local buffers
Jaroslav Hajek <highegg@gmail.com>
parents:
8379
diff
changeset
|
86 octave_local_buffer (size_t size) : octave_chunk_buffer (size * sizeof (TYPE)) { } \ |
7b6e1fc1cb90
implement obstack-like optimization of local buffers
Jaroslav Hajek <highegg@gmail.com>
parents:
8379
diff
changeset
|
87 operator TYPE *() const { return reinterpret_cast<TYPE *> (this->data ()); } \ |
7b6e1fc1cb90
implement obstack-like optimization of local buffers
Jaroslav Hajek <highegg@gmail.com>
parents:
8379
diff
changeset
|
88 } |
7b6e1fc1cb90
implement obstack-like optimization of local buffers
Jaroslav Hajek <highegg@gmail.com>
parents:
8379
diff
changeset
|
89 |
7b6e1fc1cb90
implement obstack-like optimization of local buffers
Jaroslav Hajek <highegg@gmail.com>
parents:
8379
diff
changeset
|
90 SPECIALIZE_POD_BUFFER (bool); |
7b6e1fc1cb90
implement obstack-like optimization of local buffers
Jaroslav Hajek <highegg@gmail.com>
parents:
8379
diff
changeset
|
91 SPECIALIZE_POD_BUFFER (char); |
7b6e1fc1cb90
implement obstack-like optimization of local buffers
Jaroslav Hajek <highegg@gmail.com>
parents:
8379
diff
changeset
|
92 SPECIALIZE_POD_BUFFER (unsigned short); |
7b6e1fc1cb90
implement obstack-like optimization of local buffers
Jaroslav Hajek <highegg@gmail.com>
parents:
8379
diff
changeset
|
93 SPECIALIZE_POD_BUFFER (short); |
7b6e1fc1cb90
implement obstack-like optimization of local buffers
Jaroslav Hajek <highegg@gmail.com>
parents:
8379
diff
changeset
|
94 SPECIALIZE_POD_BUFFER (int); |
7b6e1fc1cb90
implement obstack-like optimization of local buffers
Jaroslav Hajek <highegg@gmail.com>
parents:
8379
diff
changeset
|
95 SPECIALIZE_POD_BUFFER (unsigned int); |
7b6e1fc1cb90
implement obstack-like optimization of local buffers
Jaroslav Hajek <highegg@gmail.com>
parents:
8379
diff
changeset
|
96 SPECIALIZE_POD_BUFFER (long); |
7b6e1fc1cb90
implement obstack-like optimization of local buffers
Jaroslav Hajek <highegg@gmail.com>
parents:
8379
diff
changeset
|
97 SPECIALIZE_POD_BUFFER (unsigned long); |
7b6e1fc1cb90
implement obstack-like optimization of local buffers
Jaroslav Hajek <highegg@gmail.com>
parents:
8379
diff
changeset
|
98 SPECIALIZE_POD_BUFFER (float); |
7b6e1fc1cb90
implement obstack-like optimization of local buffers
Jaroslav Hajek <highegg@gmail.com>
parents:
8379
diff
changeset
|
99 SPECIALIZE_POD_BUFFER (double); |
7b6e1fc1cb90
implement obstack-like optimization of local buffers
Jaroslav Hajek <highegg@gmail.com>
parents:
8379
diff
changeset
|
100 // FIXME: Are these guaranteed to be POD and satisfy alignment? |
7b6e1fc1cb90
implement obstack-like optimization of local buffers
Jaroslav Hajek <highegg@gmail.com>
parents:
8379
diff
changeset
|
101 SPECIALIZE_POD_BUFFER (Complex); |
7b6e1fc1cb90
implement obstack-like optimization of local buffers
Jaroslav Hajek <highegg@gmail.com>
parents:
8379
diff
changeset
|
102 SPECIALIZE_POD_BUFFER (FloatComplex); |
7b6e1fc1cb90
implement obstack-like optimization of local buffers
Jaroslav Hajek <highegg@gmail.com>
parents:
8379
diff
changeset
|
103 // MORE ? |
7b6e1fc1cb90
implement obstack-like optimization of local buffers
Jaroslav Hajek <highegg@gmail.com>
parents:
8379
diff
changeset
|
104 |
7b6e1fc1cb90
implement obstack-like optimization of local buffers
Jaroslav Hajek <highegg@gmail.com>
parents:
8379
diff
changeset
|
105 // If the compiler supports dynamic stack arrays, we can use the attached hack |
7b6e1fc1cb90
implement obstack-like optimization of local buffers
Jaroslav Hajek <highegg@gmail.com>
parents:
8379
diff
changeset
|
106 // to place small buffer arrays on the stack. It may be even faster than our |
7b6e1fc1cb90
implement obstack-like optimization of local buffers
Jaroslav Hajek <highegg@gmail.com>
parents:
8379
diff
changeset
|
107 // obstack-like optimization, but is dangerous because stack is a very limited |
7b6e1fc1cb90
implement obstack-like optimization of local buffers
Jaroslav Hajek <highegg@gmail.com>
parents:
8379
diff
changeset
|
108 // resource, so we disable it. |
7b6e1fc1cb90
implement obstack-like optimization of local buffers
Jaroslav Hajek <highegg@gmail.com>
parents:
8379
diff
changeset
|
109 #if 0 //defined (HAVE_DYNAMIC_AUTO_ARRAYS) |
8377 | 110 |
111 // Maximum buffer size (in bytes) to be placed on the stack. | |
112 | |
113 #define OCTAVE_LOCAL_BUFFER_MAX_STACK_SIZE 8192 | |
114 | |
115 // If we have automatic arrays, we use an automatic array if the size is small | |
116 // enough. To avoid possibly evaluating `size' multiple times, we first cache | |
117 // it. Note that we always construct both the stack array and the | |
118 // octave_local_buffer object, but only one of them will be nonempty. | |
119 | |
120 #define OCTAVE_LOCAL_BUFFER(T, buf, size) \ | |
121 const size_t _bufsize_ ## buf = size; \ | |
122 const bool _lbufaut_ ## buf = _bufsize_ ## buf * sizeof (T) \ | |
123 <= OCTAVE_LOCAL_BUFFER_MAX_STACK_SIZE; \ | |
124 T _bufaut_ ## buf [_lbufaut_ ## buf ? _bufsize_ ## buf : 0]; \ | |
125 octave_local_buffer<T> _bufheap_ ## buf (!_lbufaut_ ## buf ? _bufsize_ ## buf : 0); \ | |
8379
ad8ed668e0a4
allow initialized local buffers
Jaroslav Hajek <highegg@gmail.com>
parents:
8377
diff
changeset
|
126 T *buf = _lbufaut_ ## buf ? _bufaut_ ## buf : static_cast<T *> (_bufheap_ ## buf) |
8377 | 127 |
128 #else | |
129 | |
130 // If we don't have automatic arrays, we simply always use octave_local_buffer. | |
131 | |
132 #define OCTAVE_LOCAL_BUFFER(T, buf, size) \ | |
133 octave_local_buffer<T> _buffer_ ## buf (size); \ | |
8379
ad8ed668e0a4
allow initialized local buffers
Jaroslav Hajek <highegg@gmail.com>
parents:
8377
diff
changeset
|
134 T *buf = _buffer_ ## buf |
8377 | 135 |
136 #endif | |
137 | |
8379
ad8ed668e0a4
allow initialized local buffers
Jaroslav Hajek <highegg@gmail.com>
parents:
8377
diff
changeset
|
138 // Yeah overloading macros would be nice. |
ad8ed668e0a4
allow initialized local buffers
Jaroslav Hajek <highegg@gmail.com>
parents:
8377
diff
changeset
|
139 // Note: we use weird variables in the for loop to avoid warnings about |
ad8ed668e0a4
allow initialized local buffers
Jaroslav Hajek <highegg@gmail.com>
parents:
8377
diff
changeset
|
140 // shadowed parameters. |
ad8ed668e0a4
allow initialized local buffers
Jaroslav Hajek <highegg@gmail.com>
parents:
8377
diff
changeset
|
141 #define OCTAVE_LOCAL_BUFFER_INIT(T, buf, size, value) \ |
ad8ed668e0a4
allow initialized local buffers
Jaroslav Hajek <highegg@gmail.com>
parents:
8377
diff
changeset
|
142 OCTAVE_LOCAL_BUFFER(T, buf, size); \ |
ad8ed668e0a4
allow initialized local buffers
Jaroslav Hajek <highegg@gmail.com>
parents:
8377
diff
changeset
|
143 for (size_t _buf_iter = 0, _buf_size = size; \ |
ad8ed668e0a4
allow initialized local buffers
Jaroslav Hajek <highegg@gmail.com>
parents:
8377
diff
changeset
|
144 _buf_iter < _buf_size; _buf_iter++) buf[_buf_iter] = value |
ad8ed668e0a4
allow initialized local buffers
Jaroslav Hajek <highegg@gmail.com>
parents:
8377
diff
changeset
|
145 |
8377 | 146 #endif |
147 |