util.h
Go to the documentation of this file.
00001 // File: $Id$
00002 // Author: John Wu <John.Wu at acm.org> Lawrence Berkeley National Laboratory
00003 // Copyright 2000-2011 the Regents of the University of California
00004 #ifndef IBIS_UTIL_H
00005 #define IBIS_UTIL_H
00006 
00007 
00008 
00009 
00010 #if defined(_WIN32) && defined(_MSC_VER) && defined(_DEBUG)
00011 #define _CRTDBG_MAP_ALLOC
00012 #include <stdlib.h>
00013 #include <crtdbg.h>
00014 #else
00015 #include <stdlib.h>
00016 #endif
00017 #include "const.h"
00018 
00019 #include <cctype>       // std::isspace
00020 #include <cstring>      // std::strcpy
00021 #include <stdio.h>      // sprintf, remove
00022 //#if HAVE_SYS_STAT_H
00023 #include <sys/stat.h>   // stat, mkdir, chmod
00024 //#endif
00025 //#if HAVE_FCNTL_H
00026 #include <fcntl.h>      // open, close
00027 //#endif
00028 #include <map>          // std::map
00029 #include <string>       // std::string
00030 #include <limits>       // std::numeric_limits
00031 #include <sstream>      // std::ostringstream used by ibis::util::logger
00032 
00033 #include <float.h>
00034 #include <math.h>       // fabs, floor, ceil, log10, ...
00035 #if !defined(unix) && defined(_WIN32)
00036 #include <windows.h>
00037 #include <io.h>
00038 #include <fcntl.h>      // _O_..
00039 int truncate(const char*, uint32_t);
00040 #include <direct.h>     // _rmdir
00041 #include <sys/stat.h>   // _stat, mkdir, chmod
00042 #define rmdir _rmdir
00043 //#elif HAVE_UNISTD_H
00044 #else
00045 #include <unistd.h>     // read, lseek, truncate, rmdir
00046 #endif
00047 
00048 // minimum size for invoking mmap operation, default to 1 MB
00049 #ifndef FASTBIT_MIN_MAP_SIZE
00050 #define FASTBIT_MIN_MAP_SIZE 1048576
00051 #endif
00052 
00053 #if ! (defined(HAVE_MMAP) || defined(_MSC_VER))
00054 #  if defined(_XOPEN_SOURCE)
00055 #    define HAVE_MMAP _XOPEN_SOURCE - 0 >= 500
00056 #  elif defined(_POSIX_C_SOURCE)
00057 #    define HAVE_MMAP _POSIX_C_SOURCE - 0 >= 0
00058 #  else
00059 #    define HAVE_MMAP defined(unix)||defined(linux)||defined(__APPLE__)||defined(__CYGWIN__)
00060 #  endif
00061 #endif
00062 
00063 #if (HAVE_MMAP+0>0) || (defined(_WIN32) && defined(_MSC_VER))
00064 #define HAVE_FILE_MAP 1
00065 #endif
00066 
00067 #ifndef DBL_EPSILON
00068 #define DBL_EPSILON 2.2204460492503131e-16
00069 #else
00070 // some wrongly define it to be 1.1e-16
00071 #undef  DBL_EPSILON
00072 #define DBL_EPSILON 2.2204460492503131e-16
00073 #endif
00074 
00075 #ifndef FASTBIT_FLOAT_NULL
00076 #define FASTBIT_FLOAT_NULL std::numeric_limits<float>::quiet_NaN()
00077 #endif
00078 #ifndef FASTBIT_DOUBLE_NULL
00079 #define FASTBIT_DOUBLE_NULL std::numeric_limits<double>::quiet_NaN()
00080 #endif
00081 
00083 #if !defined(HAVE_GCC_ATOMIC32) && defined(WITHOUT_FASTBIT_CONFIG_H)
00084 #if __GNUC__+0 >= 4 && !defined(__CYGWIN__) && !defined(__PATHCC__) && !defined(__APPLE__)
00085 #define HAVE_GCC_ATOMIC32 2
00086 #endif
00087 #endif
00088 #if !defined(HAVE_GCC_ATOMIC64) && defined(WITHOUT_FASTBIT_CONFIG_H)
00089 #if defined(__IA64__) || defined(__x86_64__) || defined(__ppc64__)
00090 #if __GNUC__+0 >= 4 && !defined(__CYGWIN__) && !defined(__PATHCC__) && !defined(__APPLE__)
00091 #define HAVE_GCC_ATOMIC64 2
00092 #endif
00093 #endif
00094 #endif
00095 
00097 #if defined(_MSC_VER) && defined(_WIN32)
00098 #ifndef HAVE_WIN_ATOMIC32
00099 #if defined(NTDDI_VERSION) && defined(NTDDI_WIN2K)
00100 #if NTDDI_VERSION >= NTDDI_WIN2K
00101 #define HAVE_WIN_ATOMIC32
00102 #endif
00103 #elif defined(WINVER)
00104 #if WINVER >= 0x0500
00105 #define HAVE_WIN_ATOMIC32
00106 #endif
00107 #endif
00108 #endif
00109 #ifndef HAVE_WIN_ATOMIC64
00110 #if defined(NTDDI_VERSION) && defined(NTDDI_WINVISTA)
00111 #if NTDDI_VERSION >= NTDDI_WINVISTA
00112 #define HAVE_WIN_ATOMIC64
00113 #endif
00114 #elif defined(WINVER)
00115 #if WINVER >= 0x0600
00116 #define HAVE_WIN_ATOMIC64
00117 #endif
00118 #endif
00119 #endif
00120 #endif
00121 
00122 // mapping the names of the low level IO functions defined in <unistd.h>
00123 #if defined(_MSC_VER) && defined(_WIN32)
00124 #define UnixOpen  ::_open
00125 #define UnixClose ::_close
00126 #define UnixRead  ::_read
00127 #define UnixWrite ::_write
00128 #define UnixSeek  ::_lseek
00129 #define UnixFlush  ::_commit
00130 #define UnixSnprintf ::_snprintf
00131 #define UnixStat  ::_stat
00132 #define UnixFStat ::_fstat
00133 #define Stat_T    struct _stat
00134 #else
00135 #define UnixOpen  ::open
00136 #define UnixClose ::close
00137 #define UnixRead  ::read
00138 #define UnixWrite ::write
00139 #define UnixSeek  ::lseek
00140 #define UnixFlush ::fsync
00141 #define UnixSnprintf ::snprintf
00142 #define UnixStat  ::stat
00143 #define UnixFStat ::fstat
00144 #define Stat_T    struct stat
00145 #endif
00146 
00147 // define the option for opening a file in read only mode
00148 #if defined(O_RDONLY)
00149 #if defined(O_LARGEFILE)
00150 #if defined(O_BINARY)
00151 #define OPEN_READONLY O_RDONLY | O_BINARY | O_LARGEFILE
00152 #else
00153 #define OPEN_READONLY O_RDONLY | O_LARGEFILE
00154 #endif
00155 #elif defined(O_BINARY)
00156 #define OPEN_READONLY O_RDONLY | O_BINARY
00157 #else
00158 #define OPEN_READONLY O_RDONLY
00159 #endif
00160 #elif defined(_O_RDONLY)
00161 #if defined(_O_LARGEFILE)
00162 #define OPEN_READONLY _O_RDONLY | _O_LARGEFILE | _O_BINARY
00163 #else
00164 #define OPEN_READONLY _O_RDONLY | _O_BINARY
00165 #endif
00166 #endif
00167 // define the option for opening a new file for writing
00168 #if defined(O_WRONLY)
00169 #if defined(O_LARGEFILE)
00170 #if defined(O_BINARY)
00171 #define OPEN_WRITENEW O_WRONLY | O_BINARY | O_CREAT | O_TRUNC | O_LARGEFILE
00172 #else
00173 #define OPEN_WRITENEW O_WRONLY | O_CREAT | O_TRUNC | O_LARGEFILE
00174 #endif
00175 #elif defined(O_BINARY)
00176 #define OPEN_WRITENEW O_WRONLY | O_BINARY | O_CREAT | O_TRUNC
00177 #else
00178 #define OPEN_WRITENEW O_WRONLY | O_CREAT | O_TRUNC
00179 #endif
00180 #elif defined(_O_WRONLY)
00181 #if defined(_O_LARGEFILE)
00182 #define OPEN_WRITENEW _O_WRONLY|_O_CREAT|_O_TRUNC|_O_LARGEFILE|_O_BINARY
00183 #else
00184 #define OPEN_WRITENEW _O_WRONLY|_O_CREAT|_O_TRUNC|_O_BINARY
00185 #endif
00186 #endif
00187 // define the option for opening an existing file for writing
00188 #if defined(O_WRONLY)
00189 #if defined(O_LARGEFILE)
00190 #if defined(O_BINARY)
00191 #define OPEN_WRITEADD O_WRONLY | O_BINARY | O_CREAT | O_LARGEFILE
00192 #else
00193 #define OPEN_WRITEADD O_WRONLY | O_CREAT| O_LARGEFILE
00194 #endif
00195 #elif defined(O_BINARY)
00196 #define OPEN_WRITEADD O_WRONLY | O_BINARY | O_CREAT
00197 #else
00198 #define OPEN_WRITEADD O_WRONLY | O_CREAT
00199 #endif
00200 #elif defined(_O_WRONLY)
00201 #if defined(_O_LARGEFILE)
00202 #define OPEN_WRITEADD _O_WRONLY | _O_CREAT | _O_LARGEFILE | _O_BINARY
00203 #else
00204 #define OPEN_WRITEADD _O_WRONLY | _O_CREAT | _O_BINARY
00205 #endif
00206 #endif
00207 // define the option for opening a file for reading and writing
00208 #if defined(O_RDWR)
00209 #if defined(O_LARGEFILE)
00210 #if defined(O_BINARY)
00211 #define OPEN_READWRITE O_RDWR | O_BINARY | O_CREAT | O_LARGEFILE
00212 #else
00213 #define OPEN_READWRITE O_RDWR | O_CREAT | O_LARGEFILE
00214 #endif
00215 #elif defined(O_BINARY)
00216 #define OPEN_READWRITE O_RDWR | O_BINARY | O_CREAT
00217 #else
00218 #define OPEN_READWRITE O_RDWR | O_CREAT
00219 #endif
00220 #elif defined(_O_RDWR)
00221 #if defined(_O_LARGEFILE)
00222 #define OPEN_READWRITE _O_RDWR | _O_CREAT | _O_LARGEFILE | _O_BINARY
00223 #else
00224 #define OPEN_READWRITE _O_RDWR | _O_CREAT | _O_BINARY
00225 #endif
00226 #endif
00227 // define the option for opening an existing file for appending only
00228 #if defined(O_WRONLY)
00229 #if defined(O_LARGEFILE)
00230 #if defined(O_BINARY)
00231 #define OPEN_APPENDONLY O_WRONLY | O_BINARY | O_CREAT | O_APPEND | O_LARGEFILE
00232 #else
00233 #define OPEN_APPENDONLY O_WRONLY | O_CREAT | O_APPEND | O_LARGEFILE
00234 #endif
00235 #elif defined(O_BINARY)
00236 #define OPEN_APPENDONLY O_WRONLY | O_BINARY | O_CREAT | O_APPEND
00237 #else
00238 #define OPEN_APPENDONLY O_WRONLY | O_CREAT | O_APPEND
00239 #endif
00240 #elif defined(_O_WRONLY)
00241 #if defined(_O_LARGEFILE)
00242 #define OPEN_APPENDONLY _O_WRONLY | _O_CREAT | _O_APPEND | _O_LARGEFILE | _O_BINARY
00243 #else
00244 #define OPEN_APPENDONLY _O_WRONLY | _O_CREAT | _O_APPEND | _O_BINARY
00245 #endif
00246 #endif
00247 // the default file mode (associate with _O_CREAT)
00248 #if defined(_MSC_VER) && defined(_WIN32)
00249 #define OPEN_FILEMODE _S_IREAD | _S_IWRITE
00250 #elif defined(S_IRGRP) && defined(S_IWGRP) && defined(S_IROTH)
00251 #define OPEN_FILEMODE S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH
00252 #else
00253 #define OPEN_FILEMODE S_IRUSR | S_IWUSR
00254 #endif
00255 
00256 #if defined(_WIN32) && defined(_MSC_VER)
00257 // needed for numeric_limits<>::max, min function calls
00258 #ifdef max
00259 #undef max
00260 #endif
00261 #ifdef min
00262 #undef min
00263 #endif
00264 #endif
00265 
00266 // The function isfinite is a macro defined in math.h according to
00267 // opengroup.org.  As of 2011, only MS visual studio does not have a
00268 // definition for isfinite, but it has _finite in float,h.
00269 #ifndef isfinite
00270 inline int isfinite(double x) {
00271 #if defined(_MSC_VER) && defined(_WIN32)
00272     return _finite(x);
00273 #else
00274     return finite(x);
00275 #endif
00276 }
00277 #endif
00278 
00279 #define LOGGER(v) \
00280 if (false == (v)) ; else ibis::util::logger(0)() 
00281 #define IBIS_BLOCK_GUARD \
00282     ibis::util::guard guard##__LINE__ = ibis::util::makeGuard
00283 
00284 namespace std { // extend namespace std slightly
00285     // specialization of less<> to work with char*
00286     template <> struct less< char* > {
00287         bool operator()(const char*x, const char*y) const {
00288             return strcmp(x, y) < 0;
00289         }
00290     };
00291 
00292     // specialization of less<> on const char* (case sensitive comparison)
00293     template <> struct less< const char* > {
00294         bool operator()(const char* x, const char* y) const {
00295             return strcmp(x, y) < 0;
00296         }
00297     };
00298 
00299     template <> struct less< ibis::rid_t > {
00300         bool operator()(const ibis::rid_t& x, const ibis::rid_t& y) const {
00301             return (x < y);
00302         }
00303     };
00304 
00305     template <> struct less< const ibis::rid_t* > {
00306         bool operator()(const ibis::rid_t* x, const ibis::rid_t* y) const {
00307             return (*x < *y);
00308         }
00309     };
00310 } // namespace std
00311 
00312 namespace ibis {
00315     class resource;     
00316     class bitvector;    
00317     class column;       
00318     class fileManager;  
00319     class horometer;    
00320     class index;        
00321     class roster;       
00322     class bitvector64;  
00323 
00324     class dictionary;   
00325     class bundle;       
00326     class colValues;    
00327 
00328     class fromClause;   
00329     class whereClause;  
00330     class selectClause; 
00331 
00332 
00334     extern FASTBIT_CXX_DLLSPEC partList datasets;
00335     ibis::part* findDataset(const char*);
00336 
00337     typedef std::vector<colValues*> colList; 
00338 
00340     FASTBIT_CXX_DLLSPEC ibis::resource& gParameters();
00341 
00344     class FASTBIT_CXX_DLLSPEC nameList {
00345     public:
00346         nameList() : cstr(0), buff(0) {};
00347         nameList(const char* str) : cstr(0), buff(0) {select(str);}
00348         ~nameList() {if (cstr) clear();}
00349 
00350         bool empty() const {return cstr == 0;}
00351         const char* operator*() const {return cstr;};
00352         uint32_t size() const {return cvec.size();};
00353 
00355         void select(const char* str);
00357         void add(const char* str);
00361         uint32_t find(const char* key) const;
00362 
00363         const char* operator[](uint32_t i) const {return cvec[i];}
00364         typedef std::vector< const char* >::const_iterator const_iterator;
00365         const_iterator begin() const {return cvec.begin();}
00366         const_iterator end() const {return cvec.end();}
00367 
00368         void clear()
00369         {cvec.clear(); delete [] cstr; delete [] buff; buff=0; cstr=0;}
00370 
00371     private:
00372         typedef std::vector< const char * > compStore;
00373         char* cstr;     // copy of the names as a single string
00374         char* buff;     // same as cstr, but delimiter is \0
00375         compStore cvec; // contains pointers to buff, for easier access
00376 
00377         nameList(const nameList&);
00378         nameList& operator=(const nameList&);
00379     }; // class nameList
00380 
00383     typedef std::map< const char*, part*, lessi > partAssoc;
00384 
00386     class bad_alloc : public std::bad_alloc {
00387     public:
00391         bad_alloc(const char *m="unknown") throw() : mesg_(m) {};
00392         virtual ~bad_alloc() throw() {}
00393         virtual const char* what() const throw() {return mesg_;}
00394 
00395     private:
00398         const char *mesg_;
00399     }; // bad_alloc
00400 
00402     namespace util {
00404         extern const char* charTable;
00406         extern const short unsigned charIndex[];
00408         extern const char* delimiters;
00415         extern FASTBIT_CXX_DLLSPEC pthread_mutex_t envLock;
00416 
00418         inline char* trim(char* str);
00420         char* strnewdup(const char* s);
00422         char* strnewdup(const char* s, const uint32_t n);
00424         inline void removeTail(char* str, char tail);
00425         char* getString(const char* buf);
00426         const char* getToken(char*& str, const char* tok_chrs);
00427         int readInt(int64_t& val, const char *&str,
00428                     const char* del=ibis::util::delimiters);
00429         int readUInt(uint64_t& val, const char *&str,
00430                      const char* del=ibis::util::delimiters);
00431         int readDouble(double& val, const char *&str,
00432                        const char* del=ibis::util::delimiters);
00433         FASTBIT_CXX_DLLSPEC int readString(std::string& str, const char*& buf,
00434                                            const char *delim=0);
00435 
00438         void removeDir(const char* name, bool leaveDir=false);
00440         int makeDir(const char* dir);
00443         FASTBIT_CXX_DLLSPEC off_t getFileSize(const char* name);
00446         int copy(const char* to, const char* from);
00447 
00451         inline void setVerboseLevel(int v) {ibis::gVerbose=v;}
00453         FASTBIT_CXX_DLLSPEC const char* userName();
00455         uint32_t serialNumber();
00458         void uniformFraction(const long unsigned idx,
00459                              long unsigned &denominator,
00460                              long unsigned &numerator);
00461         inline double rand(); 
00462 
00465         FASTBIT_CXX_DLLSPEC uint32_t checksum(const char* str, uint32_t sz);
00466         inline uint32_t checksum(uint32_t a, uint32_t b);
00467         inline std::string shortName(const std::string& longname);
00469 
00471         void int2string(std::string &str, unsigned val);
00472         void int2string(std::string &str, unsigned v1, unsigned v2);
00473         void int2string(std::string &str, unsigned v1,
00474                         unsigned v2, unsigned v3);
00475         void int2string(std::string &str, const std::vector<unsigned>& val);
00476         void encode64(uint64_t, std::string&);
00477         int  decode64(uint64_t&, const std::string&);
00478         int  decode16(uint64_t&, const char*);
00479         std::string groupby1000(uint64_t);
00481 
00484         double incrDouble(const double&);
00485         double decrDouble(const double&);
00486         void   eq2range(const double&, double&, double&);
00489         inline double coarsen(const double in, unsigned prec=2);
00492         double compactValue(double left, double right,
00493                             double start=0.0);
00494 
00497         double compactValue2(double left, double right,
00498                              double start=0.0);
00499 
00501         void setNaN(double& val);
00502         void setNaN(float& val);
00503 
00507         template <typename Tin, typename Tout>
00508         void round_down(const Tin& inval, Tout& outval) {
00509             outval = ((double)std::numeric_limits<Tout>::min() > inval ?
00510                       std::numeric_limits<Tout>::min() :
00511                       (double)std::numeric_limits<Tout>::max() <= inval ?
00512                       std::numeric_limits<Tout>::max() :
00513                       static_cast<Tout>(inval));
00514         }
00518         template <typename Tin, typename Tout>
00519         void round_up(const Tin& inval, Tout& outval) {
00520             outval = ((double)std::numeric_limits<Tout>::min() >= inval ?
00521                       std::numeric_limits<Tout>::min() :
00522                       (double) std::numeric_limits<Tout>::max() < inval ?
00523                       std::numeric_limits<Tout>::max() :
00524                       static_cast<Tout>(inval) +
00525                       ((inval-static_cast<Tin>(static_cast<Tout>(inval))) > 0));
00526         }
00528         template <typename Tin>
00529         void round_up(const Tin& inval, float&);
00531         template <typename Tin>
00532         void round_up(const Tin& inval, double& outval) {
00533             outval = static_cast<double>(inval);
00534         }
00536 
00537         FASTBIT_CXX_DLLSPEC void
00538         logMessage(const char* event, const char* fmt, ...);
00539         FASTBIT_CXX_DLLSPEC FILE* getLogFile();
00540         int writeLogFileHeader(FILE *fptr, const char* fname);
00541         FASTBIT_CXX_DLLSPEC void closeLogFile();
00542         FASTBIT_CXX_DLLSPEC int setLogFileName(const char* filename);
00543         FASTBIT_CXX_DLLSPEC const char* getLogFileName();
00544 
00548         FASTBIT_CXX_DLLSPEC bool strMatch(const char* str, const char* pat);
00549 
00551         const ibis::bitvector64& outerProduct(const ibis::bitvector& a,
00552                                               const ibis::bitvector& b,
00553                                               ibis::bitvector64& c);
00556         const ibis::bitvector64& outerProductUpper(const ibis::bitvector& a,
00557                                                    const ibis::bitvector& b,
00558                                                    ibis::bitvector64& c);
00559 
00561         long intersect(const std::vector<ibis::bitvector> &bits1,
00562                        const std::vector<ibis::bitvector> &bits2,
00563                        std::vector<ibis::bitvector> &res);
00565         long intersect(const std::vector<ibis::bitvector> &bits1,
00566                        const std::vector<ibis::bitvector> &bits2,
00567                        const std::vector<ibis::bitvector> &bits3,
00568                        std::vector<ibis::bitvector> &res);
00570         void clean(std::vector<ibis::bitvector*> &bv) throw();
00571         void clean(ibis::partList &pl) throw();
00572         // void clearDatasets(void);
00573         void updateDatasets(void);
00574 
00577         inline const char* getVersionString() {
00578             return FASTBIT_STRING;
00579         }
00581         inline int getVersionNumber() {
00582 #ifdef FASTBIT_IBIS_INT_VERSION
00583             return FASTBIT_IBIS_INT_VERSION;
00584 #else
00585             return 01010000;
00586 #endif
00587         }
00588 
00590         void getLocalTime(char *str);
00592         void getGMTime(char *str);
00593         void secondsToString(const time_t, char *str);
00594 
00595 
00596 #if defined(WIN32) && ! defined(__CYGWIN__)
00597         char* getpass_r(const char *prompt, char *buffer, uint32_t buflen);
00598         char* getpass(const char* prompt);
00599 #else
00600         inline char *itoa(int value, char *str, int /* radix */) {
00601             sprintf(str,"%d",value);
00602             return str;
00603         }
00604 #endif
00605 
00614         class FASTBIT_CXX_DLLSPEC logger {
00615         public:
00617             logger(int blanks=0);
00619             ~logger();
00621             std::ostream& operator()(void) {return mybuffer;}
00622 
00623         protected:
00625             std::ostringstream mybuffer;
00626 
00627         private:
00628             logger(const logger&);
00629             logger& operator=(const logger&);
00630         }; // logger
00631 
00634         class ioLock {
00635         public:
00636             ioLock() {
00637 #if defined(PTW32_STATIC_LIB)
00638                 if (mutex == PTHREAD_MUTEX_INITIALIZER) {
00639                     int ierr = pthread_mutex_init(&mutex, 0);
00640                     if (ierr != 0)
00641                         throw "ioLock failed to initialize the necessary mutex";
00642                 }
00643 #endif
00644                 if (0 != pthread_mutex_lock(&mutex))
00645                     throw "ioLock failed to obtain a lock";
00646             }
00647             ~ioLock() {
00648                 (void) pthread_mutex_unlock(&mutex);
00649             }
00650         private:
00651             // every instantiation of this class locks on the same mutex
00652             static pthread_mutex_t mutex;
00653 
00654             ioLock(const ioLock&) {}; // can not copy
00655             ioLock& operator=(const ioLock&);
00656         };
00657 
00659         class mutexLock {
00660         public:
00661             mutexLock(pthread_mutex_t* lk, const char* m)
00662                 : mesg(m), lock(lk) {
00663                 LOGGER(ibis::gVerbose > 10)
00664                     << "util::mutexLock -- acquiring lock (" << lock
00665                     << ") for " << mesg;
00666                 if (0 != pthread_mutex_lock(lock)) {
00667                     throw "mutexLock failed to obtain a lock";
00668                 }
00669             }
00670             ~mutexLock() {
00671                 LOGGER(ibis::gVerbose > 10)
00672                     << "util::mutexLock -- releasing lock (" << lock
00673                     << ") for " << mesg;
00674                 (void) pthread_mutex_unlock(lock);
00675             }
00676 
00677         private:
00678             const char *mesg;
00679             pthread_mutex_t *lock;
00680 
00681             mutexLock() : mesg(0), lock(0) {}; // no default constructor
00682             mutexLock(const mutexLock&); // can not copy
00683             mutexLock& operator=(const mutexLock&);
00684         }; // mutexLock
00685 
00689         class quietLock {
00690         public:
00691             quietLock(pthread_mutex_t *lk) : lock(lk) {
00692                 if (0 != pthread_mutex_lock(lock))
00693                     throw "quietLock failed to obtain a mutex lock";
00694             }
00695             ~quietLock() {
00696                 (void) pthread_mutex_unlock(lock);
00697             }
00698 
00699         private:
00700             pthread_mutex_t *lock;
00701 
00702             quietLock(); // no default constructor
00703             quietLock(const quietLock&); // can not copy
00704             quietLock& operator=(const quietLock&);
00705         }; // quietLock
00706 
00708         class readLock {
00709         public:
00710             readLock(pthread_rwlock_t* lk, const char* m)
00711                 : mesg(m), lock(lk) {
00712                 if (0 != pthread_rwlock_rdlock(lock)) {
00713                     throw "readLock failed to obtain a lock";
00714                 }
00715             }
00716             ~readLock() {
00717                 (void) pthread_rwlock_unlock(lock);
00718             }
00719 
00720         private:
00721             const char *mesg;
00722             pthread_rwlock_t *lock;
00723 
00724             readLock() : mesg(0), lock(0) {}; // no default constructor
00725             readLock(const readLock&); // can not copy
00726             readLock& operator=(const readLock&);
00727         }; // readLock
00728 
00730         class writeLock {
00731         public:
00732             writeLock(pthread_rwlock_t* lk, const char* m)
00733                 : mesg(m), lock(lk) {
00734                 if (0 != pthread_rwlock_wrlock(lock)) {
00735                     throw "writeLock failed to obtain a lock";
00736                 }
00737             }
00738             ~writeLock() {
00739                 int ierr = pthread_rwlock_unlock(lock);
00740                 if (ierr != 0) {
00741                     throw "writeLock failed to release the lock";
00742                 }
00743             }
00744 
00745         private:
00746             const char *mesg;
00747             pthread_rwlock_t *lock;
00748 
00749             writeLock() : mesg(0), lock(0) {}; // no default constructor
00750             writeLock(const writeLock&); // can not copy
00751             writeLock& operator=(const writeLock&);
00752         }; // writeLock
00753 
00760         class FASTBIT_CXX_DLLSPEC counter {
00761         public:
00762             ~counter() {
00763 #if defined(HAVE_GCC_ATOMIC32)
00764 #elif defined(HAVE_WIN_ATOMIC32)
00765 #else
00766                 (void)pthread_mutex_destroy(&lock_);
00767 #endif
00768             }
00769             counter() : count_(0) {
00770 #if defined(HAVE_GCC_ATOMIC32)
00771 #elif defined(HAVE_WIN_ATOMIC32)
00772 #else
00773                 if (0 != pthread_mutex_init(&lock_, 0))
00774                     throw ibis::bad_alloc
00775                         ("util::counter failed to initialize mutex lock");
00776 #endif
00777             }
00778 
00780             uint32_t operator()() {
00781 #if defined(HAVE_GCC_ATOMIC32)
00782                 return __sync_fetch_and_add(&count_, 1);
00783 #elif defined(HAVE_WIN_ATOMIC32)
00784                 return InterlockedIncrement((volatile long *)&count_)-1;
00785 #else
00786                 ibis::util::quietLock lck(&lock_);
00787                 uint32_t ret = count_;
00788                 ++ count_;
00789                 return ret;
00790 #endif
00791             }
00793             void reset() {
00794 #if defined(HAVE_GCC_ATOMIC32)
00795                 (void) __sync_fetch_and_sub(&count_, count_);
00796 #elif defined(HAVE_WIN_ATOMIC32)
00797                 (void) InterlockedExchange((volatile long *)&count_, 0);
00798 #else
00799                 ibis::util::quietLock lck(&lock_);
00800                 count_ = 0;
00801 #endif
00802             }
00804             uint32_t value() const {
00805                 return count_;
00806             }
00807 
00808         private:
00809 #if defined(HAVE_GCC_ATOMIC32)
00810 #elif defined(HAVE_WIN_ATOMIC32)
00811 #else
00812             mutable pthread_mutex_t lock_; 
00813 #endif
00814             volatile uint32_t count_; 
00815 
00817             counter(const counter&);
00819             counter& operator=(const counter&);
00820         }; // counter
00821 
00836         class FASTBIT_CXX_DLLSPEC sharedInt32 {
00837         public:
00838             sharedInt32() : val_(0) {
00839 #if defined(HAVE_GCC_ATOMIC32)
00840 #elif defined(HAVE_WIN_ATOMIC32)
00841 #else
00842                 if (pthread_mutex_init(&mytex, 0) != 0)
00843                     throw "pthread_mutex_init failed for sharedInt";
00844 #endif
00845             }
00846 
00847             ~sharedInt32() {
00848 #if defined(HAVE_GCC_ATOMIC32)
00849 #elif defined(HAVE_WIN_ATOMIC32)
00850 #else
00851                 (void)pthread_mutex_destroy(&mytex);
00852 #endif
00853             }
00854 
00856             uint32_t operator()() const {return val_;}
00857 
00859             uint32_t operator++() {
00860 #if defined(HAVE_GCC_ATOMIC32)
00861                 return __sync_add_and_fetch(&val_, 1);
00862 #elif defined(HAVE_WIN_ATOMIC32)
00863                 return InterlockedIncrement((volatile long *)&val_);
00864 #else
00865                 ibis::util::quietLock lock(&mytex);
00866                 ++ val_;
00867                 return val_;
00868 #endif
00869             }
00870 
00872             uint32_t operator--() {
00873 #if defined(HAVE_GCC_ATOMIC32)
00874                 return __sync_add_and_fetch(&val_, -1);
00875 #elif defined(HAVE_WIN_ATOMIC32)
00876                 return InterlockedDecrement((volatile long *)&val_);
00877 #else
00878                 ibis::util::quietLock lock(&mytex);
00879                 -- val_;
00880                 return val_;
00881 #endif
00882             }
00883 
00885             void operator+=(const uint32_t rhs) {
00886 #if defined(HAVE_GCC_ATOMIC32)
00887                 (void) __sync_add_and_fetch(&val_, rhs);
00888 #elif defined(HAVE_WIN_ATOMIC32)
00889                 (void) InterlockedExchangeAdd((volatile long *)&val_, rhs);
00890 #else
00891                 ibis::util::quietLock lock(&mytex);
00892                 val_ += rhs;
00893 #endif
00894             }
00895 
00897             void operator-=(const uint32_t rhs) {
00898 #if defined(HAVE_GCC_ATOMIC32)
00899                 (void) __sync_sub_and_fetch(&val_, rhs);
00900 #elif defined(HAVE_WIN_ATOMIC32)
00901                 (void) InterlockedExchangeAdd((volatile long *)&val_,
00902                                               -(long)rhs);
00903 #else
00904                 ibis::util::quietLock lock(&mytex);
00905                 val_ -= rhs;
00906 #endif
00907             }
00908 
00910             void swap(sharedInt32 &rhs) {
00911                 uint32_t tmp = rhs.val_;
00912                 rhs.val_ = val_;
00913                 val_ = tmp;
00914             }
00915 
00916         private:
00917             uint32_t volatile val_; 
00918 #if defined(HAVE_GCC_ATOMIC32)
00919 #elif defined(HAVE_WIN_ATOMIC32)
00920 #else
00921             pthread_mutex_t mytex; 
00922 #endif
00923 
00924             sharedInt32(const sharedInt32&); // no copy constructor
00925             sharedInt32& operator=(const sharedInt32&); // no assignment
00926         }; // sharedInt32
00927 
00934         class sharedInt64 {
00935         public:
00936             sharedInt64() : val_(0) {
00937 #if defined(HAVE_GCC_ATOMIC64)
00938 #elif defined(HAVE_WIN_ATOMIC64)
00939 #else
00940                 if (pthread_mutex_init(&mytex, 0) != 0)
00941                     throw "pthread_mutex_init failed for sharedInt";
00942 #endif
00943             }
00944 
00945             ~sharedInt64() {
00946 #if defined(HAVE_GCC_ATOMIC64)
00947 #elif defined(HAVE_WIN_ATOMIC64)
00948 #else
00949                 (void)pthread_mutex_destroy(&mytex);
00950 #endif
00951             }
00952 
00954             uint64_t operator()() const {return val_;}
00955 
00957             uint64_t operator++() {
00958 #if defined(HAVE_GCC_ATOMIC64)
00959                 return __sync_add_and_fetch(&val_, 1);
00960 #elif defined(HAVE_WIN_ATOMIC64)
00961                 return InterlockedIncrement64((volatile LONGLONG *)&val_);
00962 #else
00963                 ibis::util::quietLock lock(&mytex);
00964                 ++ val_;
00965                 return val_;
00966 #endif
00967             }
00968 
00970             uint64_t operator--() {
00971 #if defined(HAVE_GCC_ATOMIC64)
00972                 return __sync_add_and_fetch(&val_, -1);
00973 #elif defined(HAVE_WIN_ATOMIC64)
00974                 return InterlockedDecrement64((volatile LONGLONG *)&val_);
00975 #else
00976                 ibis::util::quietLock lock(&mytex);
00977                 -- val_;
00978                 return val_;
00979 #endif
00980             }
00981 
00983             void operator+=(const uint64_t rhs) {
00984 #if defined(HAVE_GCC_ATOMIC64)
00985                 (void) __sync_add_and_fetch(&val_, rhs);
00986 #elif defined(HAVE_WIN_ATOMIC64)
00987                 (void) InterlockedExchangeAdd64((volatile LONGLONG *)&val_,
00988                                                 rhs);
00989 #else
00990                 ibis::util::quietLock lock(&mytex);
00991                 val_ += rhs;
00992 #endif
00993             }
00994 
00996             void operator-=(const uint64_t rhs) {
00997 #if defined(HAVE_GCC_ATOMIC64)
00998                 (void) __sync_sub_and_fetch(&val_, rhs);
00999 #elif defined(HAVE_WIN_ATOMIC64)
01000                 (void) InterlockedExchangeAdd64((volatile LONGLONG *)&val_,
01001                                                 -(long)rhs);
01002 #else
01003                 ibis::util::quietLock lock(&mytex);
01004                 val_ -= rhs;
01005 #endif
01006             }
01007 
01009             void swap(sharedInt64 &rhs) {
01010                 uint64_t tmp = rhs.val_;
01011                 rhs.val_ = val_;
01012                 val_ = tmp;
01013             }
01014 
01015         private:
01016             uint64_t volatile val_; 
01017 #if defined(HAVE_GCC_ATOMIC64)
01018 #elif defined(HAVE_WIN_ATOMIC64)
01019 #else
01020             pthread_mutex_t mytex; 
01021 #endif
01022 
01023             sharedInt64(const sharedInt64&); // no copy constructor
01024             sharedInt64& operator=(const sharedInt64&); // no assignment
01025         }; // sharedInt64
01026 
01036         class timer {
01037         public:
01038             explicit timer(const char* msg, int lvl=1);
01039             ~timer();
01040 
01041         private:
01042             ibis::horometer *chrono_; 
01043             std::string mesg_; 
01044 
01045             timer(); // no default constructor
01046             timer(const timer&); // no copying
01047             timer& operator=(const timer&); // no assignment
01048         }; // timer
01049 
01051         template <class T> class refHolder {
01052         public:
01053             refHolder(T& r) : ref_(r) {}
01054             operator T& () const {return ref_;}
01055 
01056         private:
01057             T& ref_;
01058 
01059             refHolder();
01060         }; // refHolder
01061 
01063         template <class T>
01064         inline refHolder<T> ref(T& r) {return refHolder<T>(r);}
01065 
01068         class guardBase {
01069         public:
01072             void dismiss() const {done_ = true;}
01073 
01074         protected:
01075             mutable volatile bool done_;
01076 
01078             ~guardBase() {};
01079             guardBase() : done_(false) {}; 
01080 
01081 
01082             guardBase(const guardBase& rhs) : done_(rhs.done_) {
01083                 rhs.dismiss();
01084             }
01085 
01088             template <typename T>
01089             static void cleanup(T& task) throw () {
01090                 try {
01091                     if (!task.done_)
01092                         task.execute();
01093                 }
01094                 catch (const std::exception& e) {
01095                     LOGGER(ibis::gVerbose > 1)
01096                         << " ... caught a std::exception (" << e.what()
01097                         << ") in util::gard";
01098                 }
01099                 catch (const char* s) {
01100                     LOGGER(ibis::gVerbose > 1)
01101                         << " ... caught a string exception (" << s
01102                         << ") in util::guard";
01103                 }
01104                 catch (...) {
01105                     LOGGER(ibis::gVerbose > 1)
01106                         << " ... caught a unknown exception in util::guard";
01107                 }
01108                 task.done_ = true;
01109             }
01110         }; // guardBase
01111 
01125         typedef const guardBase& guard;
01126 
01129         template <typename F>
01130         class guardImpl0 : public guardBase {
01131         public:
01132             static guardImpl0<F> makeGuard(F f) {
01133                 return guardImpl0<F>(f);
01134             }
01135 
01137             ~guardImpl0() {cleanup(*this);}
01138 
01139         protected:
01140             friend class guardBase; // to call function execute
01141             void execute() {fun_();}
01142 
01144             explicit guardImpl0(F f) : fun_(f) {}
01145 
01146         private:
01148             F fun_;
01149 
01150             guardImpl0();
01151             guardImpl0& operator=(const guardImpl0&);
01152         }; // guardImpl0
01153 
01154         template <typename F>
01155         inline guardImpl0<F> makeGuard(F f) {
01156             return guardImpl0<F>::makeGuard(f);
01157         }
01158 
01161         template <typename F, typename A>
01162         class guardImpl1 : public guardBase {
01163         public:
01164             static guardImpl1<F, A> makeGuard(F f, A a) {
01165                 return guardImpl1<F, A>(f, a);
01166             }
01167 
01169             ~guardImpl1() {cleanup(*this);}
01170 
01171         protected:
01172             friend class guardBase; // to call function execute
01173             void execute() {fun_(arg_);}
01174 
01176             explicit guardImpl1(F f, A a) : fun_(f), arg_(a) {}
01177 
01178         private:
01180             F fun_;
01182             A arg_;
01183 
01184             guardImpl1();
01185             guardImpl1& operator=(const guardImpl1&);
01186         }; // guardImpl1
01187 
01188         template <typename F, typename A>
01189         inline guardImpl1<F, A> makeGuard(F f, A a) {
01190             return guardImpl1<F, A>::makeGuard(f, a);
01191         }
01192 
01195         template <typename F, typename A1, typename A2>
01196         class guardImpl2 : public guardBase {
01197         public:
01198             static guardImpl2<F, A1, A2> makeGuard(F f, A1 a1, A2 a2) {
01199                 return guardImpl2<F, A1, A2>(f, a1, a2);
01200             }
01201 
01203             ~guardImpl2() {cleanup(*this);}
01204 
01205         protected:
01206             friend class guardBase; // to call function execute
01207             void execute() {fun_(arg1_, arg2_);}
01208 
01210             explicit guardImpl2(F f, A1 a1, A2 a2)
01211                 : fun_(f), arg1_(a1), arg2_(a2) {}
01212 
01213         private:
01215             F fun_;
01217             A1 arg1_;
01219             A2 arg2_;
01220 
01221             guardImpl2();
01222             //guardImpl2(const guardImpl2&);
01223             guardImpl2& operator=(const guardImpl2&);
01224         }; // guardImpl2
01225 
01226         template <typename F, typename A1, typename A2>
01227         inline guardImpl2<F, A1, A2> makeGuard(F f, A1 a1, A2 a2) {
01228             return guardImpl2<F, A1, A2>::makeGuard(f, a1, a2);
01229         }
01230 
01232         template <class C, typename F>
01233         class guardObj0 : public guardBase {
01234         public:
01235             static guardObj0<C, F> makeGuard(C& o, F f) {
01236                 return guardObj0<C, F>(o, f);
01237             }
01238 
01240             ~guardObj0() {cleanup(*this);}
01241 
01242         protected:
01243             friend class guardBase; // to call function execute
01244             void execute() {(obj_.*fun_)();}
01245 
01247             guardObj0(C& o, F f) : obj_(o), fun_(f) {}
01248 
01249         private:
01250             C& obj_; 
01251             F fun_;  
01252 
01253             guardObj0();
01254             guardObj0& operator=(const guardObj0&);
01255         }; // guardObj0
01256 
01257         template <class C, typename F>
01258         inline guardObj0<C, F> objectGuard(C o, F f) {
01259             return guardObj0<C, F>::makeGuard(o, f);
01260         }
01261     } // namespace util
01262 } // namespace ibis
01263 
01264 #if defined(WIN32) && ! defined(__CYGWIN__)
01265 char* getpass(const char* prompt);
01266 #endif
01267 
01272 inline double ibis::util::rand() {
01275     static uint32_t seed = 1;
01276     static const uint32_t alpha = 69069;
01277     static const double scale = ::pow(0.5, 32);
01278     seed = static_cast<uint32_t>(seed * alpha);
01279     return(scale * seed);
01280 } // ibis::util::rand
01281 
01283 inline uint32_t ibis::util::checksum(uint32_t a, uint32_t b) {
01284     uint32_t a0 = (a >> 16);
01285     uint32_t a1 = (a & 0xFFFF);
01286     uint32_t b0 = (b >> 16);
01287     uint32_t b1 = (b & 0xFFFF);
01288     return ((((a0<<2)+a1*3+(b0<<1)+b1) << 16) | ((a0+a1+b0+b1) & 0xFFFF));
01289 } // ibis::util::checksum
01290 
01298 inline double ibis::util::incrDouble(const double& in) {
01299 #if defined(HAVE_NEXTAFTER)
01300     return nextafter(in, DBL_MAX);
01301 #elif defined(_MSC_VER) && defined(_WIN32)
01302     return _nextafter(in, DBL_MAX);
01303 #else
01304     double tmp = fabs(in) * DBL_EPSILON;
01305     if (tmp > 0.0) tmp += in;
01306     else tmp = in + DBL_MIN;
01307     return tmp;
01308 #endif
01309 }
01310 
01313 inline double ibis::util::decrDouble(const double& in) {
01314 #if defined(HAVE_NEXTAFTER)
01315     return nextafter(in, -DBL_MAX);
01316 #elif defined(_MSC_VER) && defined(_WIN32)
01317     return _nextafter(in, -DBL_MAX);
01318 #else
01319     double tmp = fabs(in) * DBL_EPSILON;
01320     if (tmp > 0.0) tmp = in - tmp;
01321     else tmp = in - DBL_MIN;
01322     return tmp;
01323 #endif
01324 }
01325 
01330 inline void ibis::util::eq2range(const double& in,
01331                                  double& left, double& right) {
01332 #if defined(HAVE_NEXTAFTER)
01333     right = nextafter(in, DBL_MAX);
01334 #elif defined(_MSC_VER) && defined(_WIN32)
01335     right = _nextafter(in, DBL_MAX);
01336 #else
01337     double tmp = fabs(in) * DBL_EPSILON;
01338     if (tmp > 0.0) {right = in + tmp;}
01339     else {right = in + DBL_MIN;}
01340 #endif
01341     left = in;
01342 } // ibis::util::eq2range
01343 
01347 template <typename Tin>
01348 inline void ibis::util::round_up(const Tin& inval, float& outval) {
01349     // perform the initial rounding
01350     outval = static_cast<float>(inval);
01351     if (static_cast<Tin>(outval) < inval) {
01352         // if the rounded value is less than the input value, compute the
01353         // next value
01354 #if defined(HAVE_NEXTAFTER)
01355         outval = nextafterf(static_cast<float>(inval), FLT_MAX);
01356 #else
01357         float tmp = fabsf(outval) * FLT_EPSILON;
01358         if (tmp > 0.0) outval += tmp;
01359         else outval += FLT_MIN;
01360 #endif
01361     }
01362 } // ibis::util::round_up
01363 
01364 // remove all the trailing char 'tail'
01365 inline void ibis::util::removeTail(char* str, char tail) {
01366     if (str != 0 && *str != 0) {
01367         char *tmp = str;
01368         while (*tmp != 0) ++ tmp;
01369         -- tmp;
01370         while (tmp > str && *tmp == tail) {
01371             *tmp = static_cast<char>(0);
01372             -- tmp;
01373         }
01374     }
01375 } // ibis::util::removeTail
01376 
01377 // remove the leading and trailing space of the incoming string
01378 inline char* ibis::util::trim(char* str) {
01379     char* head = 0;
01380     if (str == 0) return head;
01381     if (*str == 0) return head;
01382 
01383     head = str;
01384     while (*head) {
01385         if (std::isspace(*head))
01386             ++ head;
01387         else
01388             break;
01389     }
01390     if (*head == 0)
01391         return head;
01392 
01393     for (str = head; *str != 0; ++ str);
01394     -- str;
01395     while (str >= head && std::isspace(*str)) {
01396         *str = static_cast<char>(0);
01397         -- str;
01398     }
01399     return head;
01400 } // ibis::util::trim
01401 
01409 inline double ibis::util::coarsen(const double in, unsigned prec) {
01410     double ret;
01411     if (prec > 15) {
01412         ret = in;
01413     }
01414     else if (in == 0.0) {
01415         ret = in;
01416     }
01417     else {
01418         ret = fabs(in);
01419         if (ret < DBL_MIN) { // denormalized number --> 0
01420             ret = 0.0;
01421         }
01422         else if (ret < DBL_MAX) { // normal numbers
01423             ret = log10(ret);
01424             if (prec > 0)
01425                 -- prec;
01426             const int ixp = static_cast<int>(floor(ret)) -
01427                 static_cast<int>(prec);
01428             ret = floor(0.5 + pow(1e1, ret-ixp));
01429             if (ixp > 0)
01430                 ret *= pow(1e1, ixp);
01431             else if (ixp < 0)
01432                 ret /= pow(1e1, -ixp);
01433             if (in < 0.0)
01434                 ret = -ret;
01435         }
01436         else {
01437             ret = in;
01438         }
01439     }
01440     return ret;
01441 } // ibis::util::coarsen
01442 
01445 inline std::string ibis::util::shortName(const std::string& de) {
01446     std::string tn;
01447     uint32_t tmp = ibis::util::checksum(de.c_str(), de.size());
01448     ibis::util::int2string(tn, tmp);
01449     std::swap(tn[0], tn[5]);
01450     if (! isalpha(tn[0]))
01451         tn[0] = 'A' + (tn[0] % 26);
01452     return tn;
01453 } // ibis::util::shortName
01454 
01456 inline std::ostream& operator<<(std::ostream& out, const ibis::rid_t& rid) {
01457     out << '(' << rid.num.run << ", " << rid.num.event << ')';
01458     return out;
01459 }
01460 
01462 inline std::istream& operator>>(std::istream& is, ibis::rid_t& rid) {
01463     char c = 0;
01464     is >> c;
01465     if (c == '(') { // (runNumber, EventNumber)
01466         is >> rid.num.run >> c;
01467         if (c == ',')
01468             is >> rid.num.event >> c;
01469         else
01470             rid.num.event = 0;
01471         if (c != ')')
01472             is.clear(std::ios::badbit); // forget the erro
01473     }
01474     else { // runNumber, EventNumber
01475         is.putback(c);
01476         is >> rid.num.run >> c;
01477         if (c != ',') // assume space separator
01478             is.putback(c);
01479         is >> rid.num.event;
01480     }
01481     return is;
01482 }
01483 #endif // IBIS_UTIL_H

Make It A Bit Faster
Contact us
Disclaimers
FastBit source code
FastBit mailing list archive