libidx
/home/rex/ebltrunk/core/libidx/include/srg.hpp
00001 /***************************************************************************
00002  *   Copyright (C) 2008 by Yann LeCun and Pierre Sermanet *
00003  *   yann@cs.nyu.edu, pierre.sermanet@gmail.com   *
00004  *   All rights reserved.
00005  *
00006  * Redistribution and use in source and binary forms, with or without
00007  * modification, are permitted provided that the following conditions are met:
00008  *     * Redistributions of source code must retain the above copyright
00009  *       notice, this list of conditions and the following disclaimer.
00010  *     * Redistributions in binary form must reproduce the above copyright
00011  *       notice, this list of conditions and the following disclaimer in the
00012  *       documentation and/or other materials provided with the distribution.
00013  *     * Redistribution under a license not approved by the Open Source
00014  *       Initiative (http://www.opensource.org) must display the
00015  *       following acknowledgement in all advertising material:
00016  *        This product includes software developed at the Courant
00017  *        Institute of Mathematical Sciences (http://cims.nyu.edu).
00018  *     * The names of the authors may not be used to endorse or promote products
00019  *       derived from this software without specific prior written permission.
00020  *
00021  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
00022  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
00023  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
00024  * DISCLAIMED. IN NO EVENT SHALL ThE AUTHORS BE LIABLE FOR ANY
00025  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
00026  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00027  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
00028  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00029  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00030  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00031  ***************************************************************************/
00032 
00033 #ifndef SRG_HPP_
00034 #define SRG_HPP_
00035 
00036 #include <stdlib.h>
00037 #include <string.h>
00038 
00039 #ifdef __DEBUG__
00040 #include <typeinfo>
00041 #endif
00042 
00043 namespace ebl {
00044 
00046   // the creation of an idx should call lock() on the srg,
00047   // and its destruction should call unlock().
00048 
00049   // simplest constructor builds an empty srg
00050   template <typename T> srg<T>::srg() {
00051     //    refcount = 0;
00052     data = (T *)NULL;
00053     size_ = 0;
00054 #ifdef __DEBUG__
00055     smart_pointer::debug_name << "srg<" << typeid(T).name() << ">";
00056 #endif
00057   }
00058 
00059   // return size on success, and -1 on error
00060   template <typename T> srg<T>::srg(intg s) {
00061     intg r;
00062     //    refcount = 0;
00063     data = (T *)NULL;
00064     if ( ( r=this->changesize(s) ) > 0 ) this->clear();
00065     if (r < 0) { eblerror("can't allocate srg"); }
00066   }
00067 
00068   // destructor: can be called twice when the srg
00069   // is not dynamically allocated. Hence this must
00070   // make sure the data is not deallocated twice.
00071   template <typename T> srg<T>::~srg() {
00072     // DEBUG_LOW("srg::destructor: refcount = " << refcount);
00073     // if (refcount != 0) {
00074     //   eblerror("can't delete an srg with non zero refcount"); }
00075 
00076     if (data != NULL) {
00077       DEBUG_LOW("srg: freeing data " << (void*) data);
00078       free((void *) data);
00079       data = NULL;
00080 #ifdef __DEBUGMEM__
00081       this->memsize -= size_ * sizeof (T);
00082 #endif    
00083       size_ = 0;
00084     }
00085   }
00086 
00087   // return size
00088   template <typename T> intg srg<T>::size() { return size_; }
00089 
00090   // low-level resize: can grow and shrink
00091   // returns -1 on failure.
00092   // Self should be used with care, because shrinking
00093   // an srg that has idx pointing to it is very dangerous.
00094   // In most case, the grow() method should be used.
00095   template <typename T> intg srg<T>::changesize(intg s) {
00096 #ifdef __DEBUGMEM__
00097     this->memsize -= size_ * sizeof (T);
00098 #endif    
00099     if (s == 0) {
00100       free((void*) data);
00101       data = (T*) NULL;
00102       size_ = 0;
00103     } else {
00104       // TODO: malloc/realloc not thread safe
00105       // use google's tcalloc? (supposedly much faster:
00106       // http://google-perftools.googlecode.com/svn/trunk/doc/tcmalloc.html    
00107       data = (T*) realloc((void*) data, s * sizeof (T));
00108       if (data != NULL) {
00109         size_ = s;
00110 #ifdef __DEBUGMEM__
00111         this->memsize += size_ * sizeof (T);
00112 #endif
00113         DEBUG_LOW("(re)allocated data " << (void*) data);
00114         return size_;
00115       } else {
00116         size_ = 0;
00117         return -1;
00118       }
00119     }
00120 #ifdef __DEBUGMEM__
00121     this->memsize += size_ * sizeof (T);
00122 #endif    
00123     return size_;
00124   }
00125 
00126   // this grows the size of the srg if necessary.
00127   // This is called when a new idx is created on the srg.
00128   // returns -1 on failure.
00129   template <typename T> intg srg<T>::growsize(intg s) {
00130     if (s > size_) { return this->changesize(s); } else { return size_; }
00131   }
00132 
00133   template<typename T> intg srg<T>::growsize_chunk(intg s, intg s_chunk){
00134     if(s > size_) { return this->changesize(s + s_chunk); } else {return size_;}
00135   }
00136 
00137   // // decrement refcount and free if it reaches zero
00138   // template <typename T> int srg<T>::unlock() {
00139   //   refcount--;
00140   //   //if (refcount == 0) this->nopened--;
00141   //   DEBUG_LOW("srg::unlock: refcount = " << refcount << " srg " << this
00142   //          << " data " << (void*) data);
00143   //   if (refcount<0) {
00144   //     eblerror("srg negative reference counter: " << refcount);
00145   //     return refcount;
00146   //   }
00147   //   else {
00148   //     if (refcount == 0) {
00149   //    delete this;
00150   //    return 0;
00151   //     } else {
00152   //    return refcount;
00153   //     }
00154   //   }
00155   // }
00156 
00157   // // increment refcount
00158   // template <typename T> int srg<T>::lock() {
00159   //   //  if (refcount == 0) this->nopened++;
00160   //   DEBUG_LOW("srg::lock: refcount=" << refcount+1 << " srg " << this
00161   //          << " data " << (void*) data);
00162   //   return ++refcount;
00163   // }
00164 
00165   // get i-th item
00166   template <typename T> T srg<T>::get(intg i) { return data[i]; }
00167 
00168   // get i-th item
00169   template <typename T> T* srg<T>::get_data() { return data; }
00170   // set data pointer
00171   template <typename T> void srg<T>::set_data(T* ptr) { data=ptr; }
00172 
00173   // set i-th item
00174   template <typename T> void srg<T>::set(intg i, T val) { data[i] = val; }
00175 
00176   // fill with a ubyte value
00177   template <typename T> void srg<T>::clear() {
00178     memset(data, 0, size_ * sizeof(T));
00179   }
00180 
00181   // prints innards
00182   template <typename T> void srg<T>::pretty(FILE *f) {
00183     fprintf(f,"srg at address %ld; ",(long)this);
00184     fprintf(f,"size=%ld; ",size_);
00185     fprintf(f,"data=%ld; ",(long)data);
00186     //    fprintf(f,"refcount=%d\n",refcount);
00187   }
00188   
00189 } // end namespace ebl
00190 
00191 #endif /* SRG_HPP_ */