Mercurial > octave-nkf
comparison liboctave/oct-locbuf.cc @ 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 | |
children | eb63fbe60fab |
comparison
equal
deleted
inserted
replaced
8399:c1bada868690 | 8400:7b6e1fc1cb90 |
---|---|
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 #ifdef HAVE_CONFIG_H | |
24 #include <config.h> | |
25 #endif | |
26 | |
27 #include <iostream> | |
28 #include "oct-locbuf.h" | |
29 | |
30 // Query for configured chunk size, and if not defined, set it to 32 MB. | |
31 // FIXME: 32MB is hard-coded. Maybe we could use something better, like | |
32 // querying for available physical memory. | |
33 #ifndef OCTAVE_LOCBUF_CHUNKSIZE_MB | |
34 #define OCTAVE_LOCBUF_CHUNKSIZE_MB 32 | |
35 #endif | |
36 | |
37 // Each chunk will be at least this big. | |
38 const size_t octave_chunk_buffer::chunk_size = | |
39 static_cast<size_t> (OCTAVE_LOCBUF_CHUNKSIZE_MB) << 20; | |
40 | |
41 char *octave_chunk_buffer::top = 0, *octave_chunk_buffer::chunk = 0; | |
42 size_t octave_chunk_buffer::left = 0; | |
43 | |
44 octave_chunk_buffer::octave_chunk_buffer (size_t size) : cnk (0), dat (0) | |
45 { | |
46 // Alignment mask. The size of double or long int, whichever is greater. | |
47 // All data will be aligned to this size. If it's not enough for a type, | |
48 // that type should not be declared as POD. | |
49 static const size_t align_mask = (sizeof (long) < sizeof (double) | |
50 ? sizeof (double) | |
51 : sizeof (long)) - 1; | |
52 | |
53 if (! size) return; | |
54 // Align size. Note that size_t is unsigned, so size-1 must correctly | |
55 // wrap around. | |
56 size = ((size - 1) | align_mask) + 1; | |
57 | |
58 if (size > left) | |
59 { | |
60 // Big buffers (> 1/8 chunk) will be allocated as stand-alone and | |
61 // won't disrupt the chain. | |
62 if (size > chunk_size >> 3) | |
63 { | |
64 // Use new [] to get std::bad_alloc if out of memory. Could as | |
65 // well be std::malloc and handle that ourselves. | |
66 dat = new char [size]; | |
67 return; | |
68 } | |
69 | |
70 dat = new char [chunk_size]; | |
71 chunk = top = dat; | |
72 left = chunk_size; | |
73 } | |
74 | |
75 // Now allocate memory from the chunk and update state. | |
76 cnk = chunk; | |
77 dat = top; | |
78 left -= size; | |
79 top += size; | |
80 } | |
81 | |
82 octave_chunk_buffer::~octave_chunk_buffer (void) | |
83 { | |
84 if (cnk == chunk) | |
85 { | |
86 // Our chunk is still the active one. Just restore the state. | |
87 left += top - dat; | |
88 top = dat; | |
89 } | |
90 else if (! cnk) | |
91 { | |
92 // We were a stand-alone buffer. | |
93 delete [] dat; | |
94 } | |
95 else | |
96 { | |
97 // Responsible for deletion. | |
98 delete [] chunk; | |
99 chunk = cnk; | |
100 top = dat; | |
101 // FIXME: This will only work if chunk_size is constant. | |
102 left = chunk_size - (dat - cnk); | |
103 } | |
104 } |