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 }