oct-locbuf.cc

Go to the documentation of this file.
00001 /*
00002 
00003 Copyright (C) 2008-2012 Jaroslav Hajek
00004 
00005 This file is part of Octave.
00006 
00007 Octave is free software; you can redistribute it and/or modify it
00008 under the terms of the GNU General Public License as published by the
00009 Free Software Foundation; either version 3 of the License, or (at your
00010 option) any later version.
00011 
00012 Octave is distributed in the hope that it will be useful, but WITHOUT
00013 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00014 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
00015 for more details.
00016 
00017 You should have received a copy of the GNU General Public License
00018 along with Octave; see the file COPYING.  If not, see
00019 <http://www.gnu.org/licenses/>.
00020 
00021 */
00022 
00023 #ifdef HAVE_CONFIG_H
00024 #include <config.h>
00025 #endif
00026 
00027 #include <iostream>
00028 
00029 #include "lo-error.h"
00030 #include "oct-locbuf.h"
00031 
00032 // FIXME -- Maybe we should querying for available physical memory?
00033 
00034 #ifndef OCTAVE_LOCBUF_CHUNKSIZE_MB
00035 #define OCTAVE_LOCBUF_CHUNKSIZE_MB 32
00036 #endif
00037 
00038 // Each chunk will be at least this big.
00039 
00040 const size_t octave_chunk_buffer::chunk_size =
00041   static_cast<size_t> (OCTAVE_LOCBUF_CHUNKSIZE_MB) << 20;
00042 
00043 char *octave_chunk_buffer::top = 0;
00044 char *octave_chunk_buffer::chunk = 0;
00045 size_t octave_chunk_buffer::left = 0;
00046 size_t octave_chunk_buffer::active = 0;
00047 
00048 octave_chunk_buffer::octave_chunk_buffer (size_t size) : cnk (0), dat (0)
00049 {
00050   // Alignment mask. The size of double or long int, whichever is
00051   // greater.  All data will be aligned to this size.  If it's not
00052   // enough for a type, that type should not be declared as POD.
00053 
00054   static const size_t align_mask = (sizeof (long) < sizeof (double)
00055                                     ? sizeof (double)
00056                                     : sizeof (long)) - 1;
00057 
00058   active++;
00059 
00060   if (! size)
00061     return;
00062 
00063   // Align size. Note that size_t is unsigned, so size-1 must correctly
00064   // wrap around.
00065 
00066   size = ((size - 1) | align_mask) + 1;
00067 
00068   if (size > left)
00069     {
00070       // Big buffers (> 1/8 chunk) will be allocated as stand-alone and
00071       // won't disrupt the chain.
00072 
00073       if (size > chunk_size >> 3)
00074         {
00075           // Use new [] to get std::bad_alloc if out of memory.
00076 
00077           dat = new char [size];
00078           return;
00079         }
00080 
00081       dat = new char [chunk_size];
00082       chunk = top = dat;
00083       left = chunk_size;
00084     }
00085 
00086   // Now allocate memory from the chunk and update state.
00087 
00088   cnk = chunk;
00089   dat = top;
00090   left -= size;
00091   top += size;
00092 }
00093 
00094 octave_chunk_buffer::~octave_chunk_buffer (void)
00095 {
00096   active--;
00097 
00098   if (cnk == chunk)
00099     {
00100       // Our chunk is still the active one.  Just restore the state.
00101 
00102       left += top - dat;
00103       top = dat;
00104     }
00105   else
00106     {
00107       if (cnk)
00108         {
00109           // Responsible for deletion.
00110 
00111           delete [] chunk;
00112           chunk = cnk;
00113           top = dat;
00114 
00115           // FIXME -- the following calcuation of remaining data will
00116           // only work if each chunk has the same chunk_size.
00117 
00118           left = chunk_size - (dat - cnk);
00119         }
00120       else
00121         {
00122           // We were a stand-alone buffer.
00123 
00124           delete [] dat;
00125         }
00126     }
00127 }
00128 
00129 // Clear the final chunk of allocated memory.
00130 
00131 void
00132 octave_chunk_buffer::clear (void)
00133 {
00134   if (active == 0)
00135     {
00136       delete [] chunk;
00137       chunk = 0;
00138       top = 0;
00139       left = 0;
00140     }
00141   else
00142     {
00143       (*current_liboctave_warning_handler)
00144         ("octave_chunk_buffer::clear: %d active allocations remain!",
00145          active);
00146     }
00147 }
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Friends Defines