Mercurial > hg > octave-nkf
diff liboctave/oct-locbuf.cc @ 13981:5f8bc2f145f5
clean up octave_chunk_buffer storage before exit
* oct-locbuf.h, oct-locbuf.cc (octave_chunk_buffer::active):
New member variable.
(octave_chunk_buffer::clear): New static function.
(octave_chunk_buffer::octave_chunk_buffer): Update active here.
(octave_chunk_buffer::~octave_chunk_buffer): Likewise.
* toplev.cc (clean_up_and_exit): Call octave_chunk_buffer::clear.
author | John W. Eaton <jwe@octave.org> |
---|---|
date | Sat, 03 Dec 2011 03:30:27 -0500 |
parents | 12df7854fa7c |
children | 72c96de7a403 |
line wrap: on
line diff
--- a/liboctave/oct-locbuf.cc +++ b/liboctave/oct-locbuf.cc @@ -25,44 +25,55 @@ #endif #include <iostream> + +#include "lo-error.h" #include "oct-locbuf.h" -// Query for configured chunk size, and if not defined, set it to 32 MB. -// FIXME: 32MB is hard-coded. Maybe we could use something better, like -// querying for available physical memory. +// FIXME -- Maybe we should querying for available physical memory? + #ifndef OCTAVE_LOCBUF_CHUNKSIZE_MB #define OCTAVE_LOCBUF_CHUNKSIZE_MB 32 #endif // Each chunk will be at least this big. + const size_t octave_chunk_buffer::chunk_size = static_cast<size_t> (OCTAVE_LOCBUF_CHUNKSIZE_MB) << 20; -char *octave_chunk_buffer::top = 0, *octave_chunk_buffer::chunk = 0; +char *octave_chunk_buffer::top = 0; +char *octave_chunk_buffer::chunk = 0; size_t octave_chunk_buffer::left = 0; +size_t octave_chunk_buffer::active = 0; octave_chunk_buffer::octave_chunk_buffer (size_t size) : cnk (0), dat (0) { - // Alignment mask. The size of double or long int, whichever is greater. - // All data will be aligned to this size. If it's not enough for a type, - // that type should not be declared as POD. + // Alignment mask. The size of double or long int, whichever is + // greater. All data will be aligned to this size. If it's not + // enough for a type, that type should not be declared as POD. + static const size_t align_mask = (sizeof (long) < sizeof (double) ? sizeof (double) : sizeof (long)) - 1; - if (! size) return; + active++; + + if (! size) + return; + // Align size. Note that size_t is unsigned, so size-1 must correctly // wrap around. + size = ((size - 1) | align_mask) + 1; if (size > left) { // Big buffers (> 1/8 chunk) will be allocated as stand-alone and // won't disrupt the chain. + if (size > chunk_size >> 3) { - // Use new [] to get std::bad_alloc if out of memory. Could as - // well be std::malloc and handle that ourselves. + // Use new [] to get std::bad_alloc if out of memory. + dat = new char [size]; return; } @@ -73,6 +84,7 @@ } // Now allocate memory from the chunk and update state. + cnk = chunk; dat = top; left -= size; @@ -81,24 +93,55 @@ octave_chunk_buffer::~octave_chunk_buffer (void) { + active--; + if (cnk == chunk) { - // Our chunk is still the active one. Just restore the state. + // Our chunk is still the active one. Just restore the state. + left += top - dat; top = dat; } - else if (! cnk) + else { - // We were a stand-alone buffer. - delete [] dat; + if (cnk) + { + // Responsible for deletion. + + delete [] chunk; + chunk = cnk; + top = dat; + + // FIXME -- the following calcuation of remaining data will + // only work if each chunk has the same chunk_size. + + left = chunk_size - (dat - cnk); + } + else + { + // We were a stand-alone buffer. + + delete [] dat; + } + } +} + +// Clear the final chunk of allocated memory. + +void +octave_chunk_buffer::clear (void) +{ + if (active == 0) + { + delete [] chunk; + chunk = 0; + top = 0; + left = 0; } else { - // Responsible for deletion. - delete [] chunk; - chunk = cnk; - top = dat; - // FIXME: This will only work if chunk_size is constant. - left = chunk_size - (dat - cnk); + (*current_liboctave_warning_handler) + ("octave_chunk_buffer::clear: %d active allocations remain!", + active); } }