datablock.cc

00001 
00003 
00004 //
00005 // Copyright (c) 2001-2004 California Institute of Technology
00006 // Copyright (c) 2004-2007 University of Southern California
00007 // Rob Peters <rjpeters at usc dot edu>
00008 //
00009 // created: Mon Mar 12 18:04:40 2001
00010 // commit: $Id: datablock.cc 10065 2007-04-12 05:54:56Z rjpeters $
00011 // $HeadURL: file:///lab/rjpeters/svnrepo/code/trunk/groovx/src/mtx/datablock.cc $
00012 //
00013 // --------------------------------------------------------------------
00014 //
00015 // This file is part of GroovX.
00016 //   [http://ilab.usc.edu/rjpeters/groovx/]
00017 //
00018 // GroovX is free software; you can redistribute it and/or modify it
00019 // under the terms of the GNU General Public License as published by
00020 // the Free Software Foundation; either version 2 of the License, or
00021 // (at your option) any later version.
00022 //
00023 // GroovX is distributed in the hope that it will be useful, but
00024 // WITHOUT ANY WARRANTY; without even the implied warranty of
00025 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00026 // General Public License for more details.
00027 //
00028 // You should have received a copy of the GNU General Public License
00029 // along with GroovX; if not, write to the Free Software Foundation,
00030 // Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
00031 //
00033 
00034 #ifndef GROOVX_PKGS_MTX_DATABLOCK_CC_UTC20050626084022_DEFINED
00035 #define GROOVX_PKGS_MTX_DATABLOCK_CC_UTC20050626084022_DEFINED
00036 
00037 #include "datablock.h"
00038 
00039 #include "rutz/error.h"
00040 
00041 #include <algorithm>
00042 #include <cstddef>
00043 #include <cstdlib>
00044 #include <cstring>
00045 
00046 #include "rutz/debug.h"
00047 GVX_DBG_REGISTER
00048 #include "rutz/trace.h"
00049 
00050 namespace
00051 {
00052   struct FreeNode
00053   {
00054     FreeNode* next;
00055   };
00056 
00057   FreeNode* fs_free_list = 0;
00058 
00059   class shared_data_block : public data_block
00060   {
00061   public:
00062     shared_data_block(int length);
00063     virtual ~shared_data_block();
00064 
00065     virtual bool is_unique() const { return refcount() <= 1; }
00066   };
00067 
00068   shared_data_block::shared_data_block(int length) :
00069     data_block(new double[length], length)
00070   {
00071     GVX_TRACE("shared_data_block::shared_data_block");
00072     dbg_eval(3, this); dbg_eval_nl(3, m_storage);
00073   }
00074 
00075   shared_data_block::~shared_data_block()
00076   {
00077     GVX_TRACE("shared_data_block::~shared_data_block");
00078     dbg_eval(3, this); dbg_eval_nl(3, m_storage);
00079     delete [] m_storage;
00080   }
00081 
00082   class borrowed_data_block : public data_block
00083   {
00084   public:
00085     borrowed_data_block(double* borrowed_data, unsigned int length) :
00086       data_block(borrowed_data, length)
00087     {}
00088 
00089     virtual ~borrowed_data_block()
00090     { /* don't delete the data, since they are 'borrowed' */ }
00091 
00092     // Since the data are borrowed, we always return false here.
00093     virtual bool is_unique() const { return false; }
00094   };
00095 
00096   class referred_data_block : public data_block
00097   {
00098   public:
00099     referred_data_block(double* referred_data, unsigned int length) :
00100       data_block(referred_data, length)
00101     {}
00102 
00103     virtual ~referred_data_block()
00104     { /* don't delete the data, since they are 'borrowed' */ }
00105 
00106     virtual bool is_unique() const { return refcount() <= 1; }
00107   };
00108 }
00109 
00110 void* data_block::operator new(size_t bytes)
00111 {
00112 GVX_TRACE("data_block::operator new");
00113 
00114   GVX_ASSERT(bytes == sizeof(data_block));
00115   if (fs_free_list == 0)
00116     return ::operator new(bytes);
00117   FreeNode* node = fs_free_list;
00118   fs_free_list = fs_free_list->next;
00119   return (void*)node;
00120 }
00121 
00122 void data_block::operator delete(void* space)
00123 {
00124 GVX_TRACE("data_block::operator delete");
00125 
00126   ((FreeNode*)space)->next = fs_free_list;
00127   fs_free_list = (FreeNode*)space;
00128 }
00129 
00130 data_block::data_block(double* data, unsigned int len) :
00131   m_refcount(0),
00132   m_storage(data),
00133   m_length(len)
00134 {
00135 GVX_TRACE("data_block::data_block");
00136 }
00137 
00138 data_block::~data_block()
00139 {
00140 GVX_TRACE("data_block::~data_block");
00141 }
00142 
00143 data_block* data_block::get_empty_data_block()
00144 {
00145 GVX_TRACE("data_block::get_empty_data_block");
00146   static data_block* empty_rep = 0;
00147   if (empty_rep == 0)
00148     {
00149       empty_rep = new shared_data_block(0);
00150       empty_rep->incr_refcount();
00151     }
00152 
00153   return empty_rep;
00154 }
00155 
00156 data_block* data_block::make_data_copy(const double* data, int data_length)
00157 {
00158 GVX_TRACE("data_block::make_data_copy");
00159   if (data == 0)
00160     return get_empty_data_block();
00161 
00162   data_block* p = new shared_data_block(data_length);
00163 
00164   memcpy(p->m_storage, data, data_length*sizeof(double));
00165 
00166   return p;
00167 }
00168 
00169 data_block* data_block::make_zeros(int length)
00170 {
00171 GVX_TRACE("data_block::make_zeros");
00172   if (length <= 0)
00173     return get_empty_data_block();
00174 
00175   data_block* p = new shared_data_block(length);
00176   memset(p->m_storage, 0, length*sizeof(double));
00177 
00178   return p;
00179 }
00180 
00181 data_block* data_block::make_uninitialized(int length)
00182 {
00183 GVX_TRACE("data_block::make_uninitialized");
00184   if (length <= 0)
00185     return get_empty_data_block();
00186 
00187   return new shared_data_block(length);
00188 }
00189 
00190 data_block* data_block::make_borrowed(double* data, int data_length)
00191 {
00192 GVX_TRACE("data_block::make_borrowed");
00193   return new borrowed_data_block(data, data_length);
00194 }
00195 
00196 data_block* data_block::make_referred(double* data, int data_length)
00197 {
00198 GVX_TRACE("data_block::make_referred");
00199   return new referred_data_block(data, data_length);
00200 }
00201 
00202 data_block* data_block::make(double* data,
00203                              int mrows, int ncols,
00204                              mtx_policies::storage_policy s)
00205 {
00206   switch (s)
00207     {
00208     case mtx_policies::BORROW:
00209       return data_block::make_borrowed(data, mrows*ncols);
00210 
00211     case mtx_policies::REFER:
00212       return data_block::make_referred(data, mrows*ncols);
00213 
00214     case mtx_policies::COPY:
00215     default:
00216       break;
00217     }
00218 
00219   return data_block::make_data_copy(data, mrows*ncols);
00220 }
00221 
00222 data_block* data_block::make(int mrows, int ncols,
00223                              mtx_policies::init_policy p)
00224 {
00225   if (p == mtx_policies::ZEROS)
00226     return data_block::make_zeros(mrows*ncols);
00227   // else...
00228   return data_block::make_uninitialized(mrows*ncols);
00229 }
00230 
00231 void data_block::make_unique(data_block*& rep)
00232 {
00233   if (rep->is_unique()) return;
00234 
00235   {
00236     GVX_TRACE("data_block::make_unique");
00237 
00238     data_block* rep_copy = make_data_copy(rep->m_storage, rep->m_length);
00239 
00240     // do the swap
00241 
00242     rep->decr_refcount();
00243     rep_copy->incr_refcount();
00244 
00245     rep = rep_copy;
00246 
00247     GVX_POSTCONDITION(rep->m_refcount == 1);
00248   }
00249 }
00250 
00252 //
00253 // data_holder member functions
00254 //
00256 
00257 data_holder::data_holder(double* data, int mrows, int ncols, storage_policy s) :
00258   m_data(data_block::make(data, mrows, ncols, s))
00259 {
00260   m_data->incr_refcount();
00261 }
00262 
00263 data_holder::data_holder(int mrows, int ncols, init_policy p) :
00264   m_data(data_block::make(mrows, ncols, p))
00265 {
00266   m_data->incr_refcount();
00267 }
00268 
00269 data_holder::data_holder(data_block* d) :
00270   m_data(d)
00271 {
00272   m_data->incr_refcount();
00273 }
00274 
00275 data_holder::data_holder(const data_holder& other) :
00276   m_data(other.m_data)
00277 {
00278   m_data->incr_refcount();
00279 }
00280 
00281 data_holder::~data_holder()
00282 {
00283   m_data->decr_refcount();
00284 }
00285 
00286 void data_holder::swap(data_holder& other)
00287 {
00288   std::swap(m_data, other.m_data);
00289 }
00290 
00292 //
00293 // data_ref_holder definitions
00294 //
00296 
00297 void data_ref_holder::swap(data_ref_holder& other)
00298 {
00299   std::swap(m_ref, other.m_ref);
00300 }
00301 
00302 static const char __attribute__((used)) vcid_groovx_pkgs_mtx_datablock_cc_utc20050626084022[] = "$Id: datablock.cc 10065 2007-04-12 05:54:56Z rjpeters $ $HeadURL: file:
00303 #endif // !GROOVX_PKGS_MTX_DATABLOCK_CC_UTC20050626084022_DEFINED

The software described here is Copyright (c) 1998-2005, Rob Peters.
This page was generated Wed Dec 3 06:49:39 2008 by Doxygen version 1.5.5.