00001 // File: $Id$ 00002 // Author: John Wu <John.Wu at acm.org> Lawrence Berkeley National Laboratory 00003 // Copyright 2000-2012 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(LINUX) 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(LINUX) 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 #ifndef FASTBIT_CS_PATTERN_MATCH 00267 // By default use case sensitive match for string values in evaluating SQL 00268 // LIKE statements. Explicitly set this to 0 when compiling to allow case 00269 // insensitive evaluations. 00270 #define FASTBIT_CS_PATTERN_MATCH 1 00271 #endif 00272 00273 // The meta characters used in ibis::util::strMatch. 00274 #define STRMATCH_META_CSH_ANY '*' 00275 #define STRMATCH_META_CSH_ONE '?' 00276 #define STRMATCH_META_SQL_ANY '%' 00277 #define STRMATCH_META_SQL_ONE '_' 00278 #define STRMATCH_META_ESCAPE '\\' 00279 00280 // // The function isfinite is a macro defined in math.h according to 00281 // // opengroup.org. As of 2011, only MS visual studio does not have a 00282 // // definition for isfinite, but it has _finite in float,h. 00283 // #if defined(_MSC_VER) && defined(_WIN32) 00284 // inline int isfinite(double x) {return _finite(x);} 00285 // #elif !defined(isfinite) 00286 // #define isfinite finite 00287 // #endif 00288 00289 #define LOGGER(v) \ 00290 if (false == (v)) ; else ibis::util::logger(0)() 00291 // need these silly intermediate macro functions to force the arguments to 00292 // be evaluated before ## is applied 00293 #define IBIS_JOIN_MACRO2(X, Y) X##Y 00294 #define IBIS_JOIN_MACRO(X, Y) IBIS_JOIN_MACRO2(X, Y) 00295 #ifdef __GNUC__ 00296 #define IBIS_GUARD_NAME IBIS_JOIN_MACRO(_guard, __LINE__) __attribute__( ( unused ) ) 00297 #else 00298 #define IBIS_GUARD_NAME IBIS_JOIN_MACRO(_guard, __LINE__) 00299 #endif 00300 #define IBIS_BLOCK_GUARD \ 00301 ibis::util::guard IBIS_GUARD_NAME = ibis::util::makeGuard 00302 00303 namespace std { // extend namespace std slightly 00304 // specialization of less<> to work with char* 00305 template <> struct less< char* > { 00306 bool operator()(const char*x, const char*y) const { 00307 return strcmp(x, y) < 0; 00308 } 00309 }; 00310 00311 // specialization of less<> on const char* (case sensitive comparison) 00312 template <> struct less< const char* > { 00313 bool operator()(const char* x, const char* y) const { 00314 return strcmp(x, y) < 0; 00315 } 00316 }; 00317 00318 template <> struct less< ibis::rid_t > { 00319 bool operator()(const ibis::rid_t& x, const ibis::rid_t& y) const { 00320 return (x < y); 00321 } 00322 }; 00323 00324 template <> struct less< const ibis::rid_t* > { 00325 bool operator()(const ibis::rid_t* x, const ibis::rid_t* y) const { 00326 return (*x < *y); 00327 } 00328 }; 00329 } // namespace std 00330 00331 namespace ibis { 00334 class resource; 00335 class bitvector; 00336 class column; 00337 class fileManager; 00338 class horometer; 00339 class index; 00340 class roster; 00341 class bitvector64; 00342 00343 class dictionary; 00344 class bundle; 00345 class colValues; 00346 00347 class fromClause; 00348 class whereClause; 00349 class selectClause; 00350 00351 00353 extern FASTBIT_CXX_DLLSPEC partList datasets; 00354 00355 typedef std::vector<colValues*> colList; 00356 00358 FASTBIT_CXX_DLLSPEC ibis::resource& gParameters(); 00359 00362 class FASTBIT_CXX_DLLSPEC nameList { 00363 public: 00364 nameList() : cstr(0), buff(0) {}; 00365 nameList(const char* str) : cstr(0), buff(0) {select(str);} 00366 ~nameList() {if (cstr) clear();} 00367 00368 bool empty() const {return cstr == 0;} 00369 const char* operator*() const {return cstr;}; 00370 uint32_t size() const {return cvec.size();}; 00371 00373 void select(const char* str); 00375 void add(const char* str); 00379 uint32_t find(const char* key) const; 00380 00381 const char* operator[](uint32_t i) const {return cvec[i];} 00382 typedef std::vector< const char* >::const_iterator const_iterator; 00383 const_iterator begin() const {return cvec.begin();} 00384 const_iterator end() const {return cvec.end();} 00385 00386 void clear() 00387 {cvec.clear(); delete [] cstr; delete [] buff; buff=0; cstr=0;} 00388 00389 private: 00390 typedef std::vector< const char * > compStore; 00391 char* cstr; // copy of the names as a single string 00392 char* buff; // same as cstr, but delimiter is \0 00393 compStore cvec; // contains pointers to buff, for easier access 00394 00395 nameList(const nameList&); 00396 nameList& operator=(const nameList&); 00397 }; // class nameList 00398 00401 typedef std::map< const char*, part*, lessi > partAssoc; 00402 00404 class bad_alloc : public std::bad_alloc { 00405 public: 00409 bad_alloc(const char *m="unknown") throw() : mesg_(m) {}; 00410 virtual ~bad_alloc() throw() {} 00411 virtual const char* what() const throw() {return mesg_;} 00412 00413 private: 00416 const char *mesg_; 00417 }; // bad_alloc 00418 00420 namespace util { 00422 extern const char* charTable; 00424 extern const short unsigned charIndex[]; 00426 extern const char* delimiters; 00428 extern const int log2table[256]; 00435 extern FASTBIT_CXX_DLLSPEC pthread_mutex_t envLock; 00436 00438 inline char* trim(char* str); 00440 char* strnewdup(const char* s); 00442 char* strnewdup(const char* s, const uint32_t n); 00444 inline void removeTail(char* str, char tail); 00445 char* getString(const char* buf); 00446 const char* getToken(char*& str, const char* tok_chrs); 00447 int readInt(int64_t& val, const char *&str, 00448 const char* del=ibis::util::delimiters); 00449 int readUInt(uint64_t& val, const char *&str, 00450 const char* del=ibis::util::delimiters); 00451 int readDouble(double& val, const char *&str, 00452 const char* del=ibis::util::delimiters); 00453 FASTBIT_CXX_DLLSPEC int readString(std::string& str, const char*& buf, 00454 const char *delim=0); 00455 00456 int64_t read(int, void*, int64_t); 00457 00460 void removeDir(const char* name, bool leaveDir=false); 00462 int makeDir(const char* dir); 00465 FASTBIT_CXX_DLLSPEC off_t getFileSize(const char* name); 00468 int copy(const char* to, const char* from); 00469 00473 inline void setVerboseLevel(int v) {ibis::gVerbose=v;} 00475 FASTBIT_CXX_DLLSPEC const char* userName(); 00477 uint32_t serialNumber(); 00478 void uniformFraction(const long unsigned idx, 00479 long unsigned &denominator, 00480 long unsigned &numerator); 00481 inline double rand(); 00482 00484 FASTBIT_CXX_DLLSPEC uint32_t checksum(const char* str, uint32_t sz); 00485 inline uint32_t checksum(uint32_t a, uint32_t b); 00486 std::string shortName(const std::string& longname); 00487 std::string randName(const std::string& longname); 00489 00491 void int2string(std::string &str, unsigned val); 00492 void int2string(std::string &str, unsigned v1, unsigned v2); 00493 void int2string(std::string &str, unsigned v1, 00494 unsigned v2, unsigned v3); 00495 void int2string(std::string &str, const std::vector<unsigned>& val); 00496 void encode64(uint64_t, std::string&); 00497 int decode64(uint64_t&, const std::string&); 00498 int decode16(uint64_t&, const char*); 00499 std::string groupby1000(uint64_t); 00501 00504 double incrDouble(const double&); 00505 double decrDouble(const double&); 00506 void eq2range(const double&, double&, double&); 00509 inline double coarsen(const double in, unsigned prec=2); 00512 double compactValue(double left, double right, 00513 double start=0.0); 00514 00517 double compactValue2(double left, double right, 00518 double start=0.0); 00519 00521 void setNaN(double& val); 00522 void setNaN(float& val); 00523 00527 template <typename Tin, typename Tout> 00528 void round_down(const Tin& inval, Tout& outval) { 00529 outval = ((double)std::numeric_limits<Tout>::min() > inval ? 00530 std::numeric_limits<Tout>::min() : 00531 (double)std::numeric_limits<Tout>::max() <= inval ? 00532 std::numeric_limits<Tout>::max() : 00533 static_cast<Tout>(inval)); 00534 } 00538 template <typename Tin, typename Tout> 00539 void round_up(const Tin& inval, Tout& outval) { 00540 outval = ((double)std::numeric_limits<Tout>::min() >= inval ? 00541 std::numeric_limits<Tout>::min() : 00542 (double) std::numeric_limits<Tout>::max() < inval ? 00543 std::numeric_limits<Tout>::max() : 00544 static_cast<Tout>(inval) + 00545 ((inval-static_cast<Tin>(static_cast<Tout>(inval))) > 0)); 00546 } 00548 template <typename Tin> 00549 void round_up(const Tin& inval, float&); 00551 template <typename Tin> 00552 void round_up(const Tin& inval, double& outval) { 00553 outval = static_cast<double>(inval); 00554 } 00555 00557 inline int log2(uint32_t x) { 00558 register uint32_t xx, xxx; 00559 return (xx = x >> 16) 00560 ? (xxx = xx >> 8) ? 24 + log2table[xxx] : 16 + log2table[xx] 00561 : (xxx = x >> 8) ? 8 + log2table[xxx] : log2table[x]; 00562 } 00564 inline int log2(uint64_t x) { 00565 register uint32_t xx; 00566 return (xx = x >> 32) 00567 ? 32 + log2(xx) 00568 : log2(static_cast<uint32_t>(x)); 00569 } 00571 00572 FASTBIT_CXX_DLLSPEC void 00573 logMessage(const char* event, const char* fmt, ...); 00574 FASTBIT_CXX_DLLSPEC FILE* getLogFile(); 00575 int writeLogFileHeader(FILE *fptr, const char* fname); 00576 FASTBIT_CXX_DLLSPEC void closeLogFile(); 00577 FASTBIT_CXX_DLLSPEC int setLogFileName(const char* filename); 00578 FASTBIT_CXX_DLLSPEC const char* getLogFileName(); 00579 00583 FASTBIT_CXX_DLLSPEC bool strMatch(const char* str, const char* pat); 00584 00586 const ibis::bitvector64& outerProduct(const ibis::bitvector& a, 00587 const ibis::bitvector& b, 00588 ibis::bitvector64& c); 00591 const ibis::bitvector64& outerProductUpper(const ibis::bitvector& a, 00592 const ibis::bitvector& b, 00593 ibis::bitvector64& c); 00594 00596 long intersect(const std::vector<ibis::bitvector> &bits1, 00597 const std::vector<ibis::bitvector> &bits2, 00598 std::vector<ibis::bitvector> &res); 00600 long intersect(const std::vector<ibis::bitvector> &bits1, 00601 const std::vector<ibis::bitvector> &bits2, 00602 const std::vector<ibis::bitvector> &bits3, 00603 std::vector<ibis::bitvector> &res); 00604 void clear(ibis::array_t<ibis::bitvector*> &bv) throw(); 00605 void clear(ibis::partList &pl) throw(); 00606 void updateDatasets(void); 00607 00610 inline const char* getVersionString() { 00611 return FASTBIT_STRING; 00612 } 00619 inline int getVersionNumber() { 00620 #ifdef FASTBIT_IBIS_INT_VERSION 00621 return FASTBIT_IBIS_INT_VERSION; 00622 #else 00623 return 1030000; 00624 #endif 00625 } 00626 00628 void getLocalTime(char *str); 00630 void getGMTime(char *str); 00631 void secondsToString(const time_t, char *str); 00632 00633 00634 #if defined(WIN32) && ! defined(__CYGWIN__) 00635 char* getpass_r(const char *prompt, char *buffer, uint32_t buflen); 00636 char* getpass(const char* prompt); 00637 #else 00638 inline char *itoa(int value, char *str, int /* radix */) { 00639 sprintf(str,"%d",value); 00640 return str; 00641 } 00642 #endif 00643 00645 template <typename T> inline void 00646 clearVec(std::vector<T*> &v) { 00647 const size_t nv = v.size(); 00648 for (size_t j = 0; j < nv; ++j) 00649 delete v[j]; 00650 v.clear(); 00651 } // clearVec 00652 00661 class FASTBIT_CXX_DLLSPEC logger { 00662 public: 00664 logger(int blanks=0); 00666 ~logger(); 00668 std::ostream& operator()(void) {return mybuffer;} 00669 00670 protected: 00672 std::ostringstream mybuffer; 00673 00674 private: 00675 logger(const logger&); 00676 logger& operator=(const logger&); 00677 }; // logger 00678 00681 class ioLock { 00682 public: 00683 ioLock() { 00684 #if defined(PTW32_STATIC_LIB) 00685 if (mutex == PTHREAD_MUTEX_INITIALIZER) { 00686 int ierr = pthread_mutex_init(&mutex, 0); 00687 if (ierr != 0) 00688 throw "ioLock failed to initialize the necessary mutex"; 00689 } 00690 #endif 00691 if (0 != pthread_mutex_lock(&mutex)) 00692 throw "ioLock failed to obtain a lock"; 00693 } 00694 ~ioLock() { 00695 (void) pthread_mutex_unlock(&mutex); 00696 } 00697 private: 00698 // every instantiation of this class locks on the same mutex 00699 static pthread_mutex_t mutex; 00700 00701 ioLock(const ioLock&) {}; // can not copy 00702 ioLock& operator=(const ioLock&); 00703 }; 00704 00706 class mutexLock { 00707 public: 00708 mutexLock(pthread_mutex_t* lk, const char* m) 00709 : mesg(m), lock(lk) { 00710 LOGGER(ibis::gVerbose > 10) 00711 << "util::mutexLock -- acquiring lock (" << lock 00712 << ") for " << mesg; 00713 if (0 != pthread_mutex_lock(lock)) { 00714 throw "mutexLock failed to obtain a lock"; 00715 } 00716 } 00717 ~mutexLock() { 00718 LOGGER(ibis::gVerbose > 10) 00719 << "util::mutexLock -- releasing lock (" << lock 00720 << ") for " << mesg; 00721 (void) pthread_mutex_unlock(lock); 00722 } 00723 00724 private: 00725 const char *mesg; 00726 pthread_mutex_t *lock; 00727 00728 mutexLock() : mesg(0), lock(0) {}; // no default constructor 00729 mutexLock(const mutexLock&); // can not copy 00730 mutexLock& operator=(const mutexLock&); 00731 }; // mutexLock 00732 00736 class quietLock { 00737 public: 00738 quietLock(pthread_mutex_t *lk) : lock(lk) { 00739 if (0 != pthread_mutex_lock(lock)) 00740 throw "quietLock failed to obtain a mutex lock"; 00741 } 00742 ~quietLock() { 00743 (void) pthread_mutex_unlock(lock); 00744 } 00745 00746 private: 00747 pthread_mutex_t *lock; 00748 00749 quietLock(); // no default constructor 00750 quietLock(const quietLock&); // can not copy 00751 quietLock& operator=(const quietLock&); 00752 }; // quietLock 00753 00755 class readLock { 00756 public: 00757 readLock(pthread_rwlock_t* lk, const char* m) 00758 : mesg(m), lock(lk) { 00759 if (0 != pthread_rwlock_rdlock(lock)) { 00760 throw "readLock failed to obtain a lock"; 00761 } 00762 } 00763 ~readLock() { 00764 (void) pthread_rwlock_unlock(lock); 00765 } 00766 00767 private: 00768 const char *mesg; 00769 pthread_rwlock_t *lock; 00770 00771 readLock() : mesg(0), lock(0) {}; // no default constructor 00772 readLock(const readLock&); // can not copy 00773 readLock& operator=(const readLock&); 00774 }; // readLock 00775 00777 class writeLock { 00778 public: 00779 writeLock(pthread_rwlock_t* lk, const char* m) 00780 : mesg(m), lock(lk) { 00781 if (0 != pthread_rwlock_wrlock(lock)) { 00782 throw "writeLock failed to obtain a lock"; 00783 } 00784 } 00785 ~writeLock() { 00786 int ierr = pthread_rwlock_unlock(lock); 00787 if (ierr != 0) { 00788 throw "writeLock failed to release the lock"; 00789 } 00790 } 00791 00792 private: 00793 const char *mesg; 00794 pthread_rwlock_t *lock; 00795 00796 writeLock() : mesg(0), lock(0) {}; // no default constructor 00797 writeLock(const writeLock&); // can not copy 00798 writeLock& operator=(const writeLock&); 00799 }; // writeLock 00800 00807 class FASTBIT_CXX_DLLSPEC counter { 00808 public: 00809 ~counter() { 00810 #if defined(HAVE_GCC_ATOMIC32) 00811 #elif defined(HAVE_WIN_ATOMIC32) 00812 #else 00813 (void)pthread_mutex_destroy(&lock_); 00814 #endif 00815 } 00816 counter() : count_(0) { 00817 #if defined(HAVE_GCC_ATOMIC32) 00818 #elif defined(HAVE_WIN_ATOMIC32) 00819 #else 00820 if (0 != pthread_mutex_init(&lock_, 0)) 00821 throw ibis::bad_alloc 00822 ("util::counter failed to initialize mutex lock"); 00823 #endif 00824 } 00825 00827 uint32_t operator()() { 00828 #if defined(HAVE_GCC_ATOMIC32) 00829 return __sync_fetch_and_add(&count_, 1); 00830 #elif defined(HAVE_WIN_ATOMIC32) 00831 return InterlockedIncrement((volatile long *)&count_)-1; 00832 #else 00833 ibis::util::quietLock lck(&lock_); 00834 uint32_t ret = count_; 00835 ++ count_; 00836 return ret; 00837 #endif 00838 } 00840 void reset() { 00841 #if defined(HAVE_GCC_ATOMIC32) 00842 (void) __sync_fetch_and_sub(&count_, count_); 00843 #elif defined(HAVE_WIN_ATOMIC32) 00844 (void) InterlockedExchange((volatile long *)&count_, 0); 00845 #else 00846 ibis::util::quietLock lck(&lock_); 00847 count_ = 0; 00848 #endif 00849 } 00851 uint32_t value() const { 00852 return count_; 00853 } 00854 00855 private: 00856 #if defined(HAVE_GCC_ATOMIC32) 00857 #elif defined(HAVE_WIN_ATOMIC32) 00858 #else 00859 mutable pthread_mutex_t lock_; 00860 #endif 00861 volatile uint32_t count_; 00862 00864 counter(const counter&); 00866 counter& operator=(const counter&); 00867 }; // counter 00868 00883 class FASTBIT_CXX_DLLSPEC sharedInt32 { 00884 public: 00885 sharedInt32() : val_(0) { 00886 #if defined(HAVE_GCC_ATOMIC32) 00887 #elif defined(HAVE_WIN_ATOMIC32) 00888 #else 00889 if (pthread_mutex_init(&mytex, 0) != 0) 00890 throw "pthread_mutex_init failed for sharedInt"; 00891 #endif 00892 } 00893 00894 ~sharedInt32() { 00895 #if defined(HAVE_GCC_ATOMIC32) 00896 #elif defined(HAVE_WIN_ATOMIC32) 00897 #else 00898 (void)pthread_mutex_destroy(&mytex); 00899 #endif 00900 } 00901 00903 uint32_t operator()() const {return val_;} 00904 00906 uint32_t operator++() { 00907 #if defined(HAVE_GCC_ATOMIC32) 00908 return __sync_add_and_fetch(&val_, 1); 00909 #elif defined(HAVE_WIN_ATOMIC32) 00910 return InterlockedIncrement((volatile long *)&val_); 00911 #else 00912 ibis::util::quietLock lock(&mytex); 00913 ++ val_; 00914 return val_; 00915 #endif 00916 } 00917 00919 uint32_t operator--() { 00920 #if defined(HAVE_GCC_ATOMIC32) 00921 return __sync_sub_and_fetch(&val_, 1); 00922 #elif defined(HAVE_WIN_ATOMIC32) 00923 return InterlockedDecrement((volatile long *)&val_); 00924 #else 00925 ibis::util::quietLock lock(&mytex); 00926 -- val_; 00927 return val_; 00928 #endif 00929 } 00930 00932 void operator+=(const uint32_t rhs) { 00933 #if defined(HAVE_GCC_ATOMIC32) 00934 (void) __sync_add_and_fetch(&val_, rhs); 00935 #elif defined(HAVE_WIN_ATOMIC32) 00936 (void) InterlockedExchangeAdd((volatile long *)&val_, rhs); 00937 #else 00938 ibis::util::quietLock lock(&mytex); 00939 val_ += rhs; 00940 #endif 00941 } 00942 00944 void operator-=(const uint32_t rhs) { 00945 #if defined(HAVE_GCC_ATOMIC32) 00946 (void) __sync_sub_and_fetch(&val_, rhs); 00947 #elif defined(HAVE_WIN_ATOMIC32) 00948 (void) InterlockedExchangeAdd((volatile long *)&val_, 00949 -(long)rhs); 00950 #else 00951 ibis::util::quietLock lock(&mytex); 00952 val_ -= rhs; 00953 #endif 00954 } 00955 00957 void swap(sharedInt32 &rhs) { 00958 uint32_t tmp = rhs.val_; 00959 rhs.val_ = val_; 00960 val_ = tmp; 00961 } 00962 00963 private: 00964 uint32_t volatile val_; 00965 #if defined(HAVE_GCC_ATOMIC32) 00966 #elif defined(HAVE_WIN_ATOMIC32) 00967 #else 00968 pthread_mutex_t mytex; 00969 #endif 00970 00971 sharedInt32(const sharedInt32&); // no copy constructor 00972 sharedInt32& operator=(const sharedInt32&); // no assignment 00973 }; // sharedInt32 00974 00981 class sharedInt64 { 00982 public: 00983 sharedInt64() : val_(0) { 00984 #if defined(HAVE_GCC_ATOMIC64) 00985 #elif defined(HAVE_WIN_ATOMIC64) 00986 #else 00987 if (pthread_mutex_init(&mytex, 0) != 0) 00988 throw "pthread_mutex_init failed for sharedInt"; 00989 #endif 00990 } 00991 00992 ~sharedInt64() { 00993 #if defined(HAVE_GCC_ATOMIC64) 00994 #elif defined(HAVE_WIN_ATOMIC64) 00995 #else 00996 (void)pthread_mutex_destroy(&mytex); 00997 #endif 00998 } 00999 01001 uint64_t operator()() const {return val_;} 01002 01004 uint64_t operator++() { 01005 #if defined(HAVE_GCC_ATOMIC64) 01006 return __sync_add_and_fetch(&val_, 1); 01007 #elif defined(HAVE_WIN_ATOMIC64) 01008 return InterlockedIncrement64((volatile LONGLONG *)&val_); 01009 #else 01010 ibis::util::quietLock lock(&mytex); 01011 ++ val_; 01012 return val_; 01013 #endif 01014 } 01015 01017 uint64_t operator--() { 01018 #if defined(HAVE_GCC_ATOMIC64) 01019 return __sync_sub_and_fetch(&val_, 1); 01020 #elif defined(HAVE_WIN_ATOMIC64) 01021 return InterlockedDecrement64((volatile LONGLONG *)&val_); 01022 #else 01023 ibis::util::quietLock lock(&mytex); 01024 -- val_; 01025 return val_; 01026 #endif 01027 } 01028 01030 void operator+=(const uint64_t rhs) { 01031 #if defined(HAVE_GCC_ATOMIC64) 01032 (void) __sync_add_and_fetch(&val_, rhs); 01033 #elif defined(HAVE_WIN_ATOMIC64) 01034 (void) InterlockedExchangeAdd64((volatile LONGLONG *)&val_, 01035 rhs); 01036 #else 01037 ibis::util::quietLock lock(&mytex); 01038 val_ += rhs; 01039 #endif 01040 } 01041 01043 void operator-=(const uint64_t rhs) { 01044 #if defined(HAVE_GCC_ATOMIC64) 01045 (void) __sync_sub_and_fetch(&val_, rhs); 01046 #elif defined(HAVE_WIN_ATOMIC64) 01047 (void) InterlockedExchangeAdd64((volatile LONGLONG *)&val_, 01048 -(long)rhs); 01049 #else 01050 ibis::util::quietLock lock(&mytex); 01051 val_ -= rhs; 01052 #endif 01053 } 01054 01056 void swap(sharedInt64 &rhs) { 01057 uint64_t tmp = rhs.val_; 01058 rhs.val_ = val_; 01059 val_ = tmp; 01060 } 01061 01062 private: 01063 uint64_t volatile val_; 01064 #if defined(HAVE_GCC_ATOMIC64) 01065 #elif defined(HAVE_WIN_ATOMIC64) 01066 #else 01067 pthread_mutex_t mytex; 01068 #endif 01069 01070 sharedInt64(const sharedInt64&); // no copy constructor 01071 sharedInt64& operator=(const sharedInt64&); // no assignment 01072 }; // sharedInt64 01073 01083 class timer { 01084 public: 01085 explicit timer(const char* msg, int lvl=1); 01086 ~timer(); 01087 01088 private: 01089 ibis::horometer *chrono_; 01090 std::string mesg_; 01091 01092 timer(); // no default constructor 01093 timer(const timer&); // no copying 01094 timer& operator=(const timer&); // no assignment 01095 }; // timer 01096 01098 template <class T> class refHolder { 01099 public: 01100 refHolder(T& r) : ref_(r) {} 01101 operator T& () const {return ref_;} 01102 01103 private: 01104 T& ref_; 01105 01106 refHolder(); 01107 }; // refHolder 01108 01110 template <class T> 01111 inline refHolder<T> ref(T& r) {return refHolder<T>(r);} 01112 01115 class guardBase { 01116 public: 01119 void dismiss() const {done_ = true;} 01120 01121 protected: 01122 mutable volatile bool done_; 01123 01125 ~guardBase() {}; 01126 guardBase() : done_(false) {}; 01127 01128 01129 guardBase(const guardBase& rhs) : done_(rhs.done_) { 01130 rhs.dismiss(); 01131 } 01132 01135 template <typename T> 01136 static void cleanup(T& task) throw () { 01137 try { 01138 if (!task.done_) 01139 task.execute(); 01140 } 01141 catch (const std::exception& e) { 01142 LOGGER(ibis::gVerbose > 1) 01143 << " ... caught a std::exception (" << e.what() 01144 << ") in util::gard"; 01145 } 01146 catch (const char* s) { 01147 LOGGER(ibis::gVerbose > 1) 01148 << " ... caught a string exception (" << s 01149 << ") in util::guard"; 01150 } 01151 catch (...) { 01152 LOGGER(ibis::gVerbose > 1) 01153 << " ... caught a unknown exception in util::guard"; 01154 } 01155 task.done_ = true; 01156 } 01157 }; // guardBase 01158 01172 typedef const guardBase& guard; 01173 01176 template <typename F> 01177 class guardImpl0 : public guardBase { 01178 public: 01179 static guardImpl0<F> makeGuard(F f) { 01180 return guardImpl0<F>(f); 01181 } 01182 01184 ~guardImpl0() {cleanup(*this);} 01185 01186 protected: 01187 friend class guardBase; // to call function execute 01188 void execute() {fun_();} 01189 01191 explicit guardImpl0(F f) : fun_(f) {} 01192 01193 private: 01195 F fun_; 01196 01197 guardImpl0(); 01198 guardImpl0& operator=(const guardImpl0&); 01199 }; // guardImpl0 01200 01201 template <typename F> 01202 inline guardImpl0<F> makeGuard(F f) { 01203 return guardImpl0<F>::makeGuard(f); 01204 } 01205 01208 template <typename F, typename A> 01209 class guardImpl1 : public guardBase { 01210 public: 01211 static guardImpl1<F, A> makeGuard(F f, A a) { 01212 return guardImpl1<F, A>(f, a); 01213 } 01214 01216 ~guardImpl1() {cleanup(*this);} 01217 01218 protected: 01219 friend class guardBase; // to call function execute 01220 void execute() {fun_(arg_);} 01221 01223 explicit guardImpl1(F f, A a) : fun_(f), arg_(a) {} 01224 01225 private: 01227 F fun_; 01229 A arg_; 01230 01231 guardImpl1(); 01232 guardImpl1& operator=(const guardImpl1&); 01233 }; // guardImpl1 01234 01235 template <typename F, typename A> 01236 inline guardImpl1<F, A> makeGuard(F f, A a) { 01237 return guardImpl1<F, A>::makeGuard(f, a); 01238 } 01239 01242 template <typename F, typename A1, typename A2> 01243 class guardImpl2 : public guardBase { 01244 public: 01245 static guardImpl2<F, A1, A2> makeGuard(F f, A1 a1, A2 a2) { 01246 return guardImpl2<F, A1, A2>(f, a1, a2); 01247 } 01248 01250 ~guardImpl2() {cleanup(*this);} 01251 01252 protected: 01253 friend class guardBase; // to call function execute 01254 void execute() {fun_(arg1_, arg2_);} 01255 01257 explicit guardImpl2(F f, A1 a1, A2 a2) 01258 : fun_(f), arg1_(a1), arg2_(a2) {} 01259 01260 private: 01262 F fun_; 01264 A1 arg1_; 01266 A2 arg2_; 01267 01268 guardImpl2(); 01269 //guardImpl2(const guardImpl2&); 01270 guardImpl2& operator=(const guardImpl2&); 01271 }; // guardImpl2 01272 01273 template <typename F, typename A1, typename A2> 01274 inline guardImpl2<F, A1, A2> makeGuard(F f, A1 a1, A2 a2) { 01275 return guardImpl2<F, A1, A2>::makeGuard(f, a1, a2); 01276 } 01277 01279 template <class C, typename F> 01280 class guardObj0 : public guardBase { 01281 public: 01282 static guardObj0<C, F> makeGuard(C& o, F f) { 01283 return guardObj0<C, F>(o, f); 01284 } 01285 01287 ~guardObj0() {cleanup(*this);} 01288 01289 protected: 01290 friend class guardBase; // to call function execute 01291 void execute() {(obj_.*fun_)();} 01292 01294 guardObj0(C& o, F f) : obj_(o), fun_(f) {} 01295 01296 private: 01297 C& obj_; 01298 F fun_; 01299 01300 guardObj0(); 01301 guardObj0& operator=(const guardObj0&); 01302 }; // guardObj0 01303 01304 template <class C, typename F> 01305 inline guardObj0<C, F> objectGuard(C o, F f) { 01306 return guardObj0<C, F>::makeGuard(o, f); 01307 } 01308 } // namespace util 01309 } // namespace ibis 01310 01311 #if defined(WIN32) && ! defined(__CYGWIN__) 01312 char* getpass(const char* prompt); 01313 #endif 01314 01320 inline double ibis::util::rand() { 01321 // The internal variable @c seed is always an odd number. Don't use it 01322 // directly. 01323 static uint32_t seed = 1; 01324 static const uint32_t alpha = 69069; 01325 static const double scale = ::pow(0.5, 32); 01326 seed = static_cast<uint32_t>(seed * alpha); 01327 return(scale * seed); 01328 } // ibis::util::rand 01329 01331 inline uint32_t ibis::util::checksum(uint32_t a, uint32_t b) { 01332 uint32_t a0 = (a >> 16); 01333 uint32_t a1 = (a & 0xFFFF); 01334 uint32_t b0 = (b >> 16); 01335 uint32_t b1 = (b & 0xFFFF); 01336 return ((((a0<<2)+a1*3+(b0<<1)+b1) << 16) | ((a0+a1+b0+b1) & 0xFFFF)); 01337 } // ibis::util::checksum 01338 01346 inline double ibis::util::incrDouble(const double& in) { 01347 #if defined(HAVE_NEXTAFTER) 01348 return nextafter(in, DBL_MAX); 01349 #elif defined(_MSC_VER) && defined(_WIN32) 01350 return _nextafter(in, DBL_MAX); 01351 #else 01352 double tmp = fabs(in) * DBL_EPSILON; 01353 if (tmp > 0.0) tmp += in; 01354 else tmp = in + DBL_MIN; 01355 return tmp; 01356 #endif 01357 } 01358 01361 inline double ibis::util::decrDouble(const double& in) { 01362 #if defined(HAVE_NEXTAFTER) 01363 return nextafter(in, -DBL_MAX); 01364 #elif defined(_MSC_VER) && defined(_WIN32) 01365 return _nextafter(in, -DBL_MAX); 01366 #else 01367 double tmp = fabs(in) * DBL_EPSILON; 01368 if (tmp > 0.0) tmp = in - tmp; 01369 else tmp = in - DBL_MIN; 01370 return tmp; 01371 #endif 01372 } 01373 01378 inline void ibis::util::eq2range(const double& in, 01379 double& left, double& right) { 01380 #if defined(HAVE_NEXTAFTER) 01381 right = nextafter(in, DBL_MAX); 01382 #elif defined(_MSC_VER) && defined(_WIN32) 01383 right = _nextafter(in, DBL_MAX); 01384 #else 01385 double tmp = fabs(in) * DBL_EPSILON; 01386 if (tmp > 0.0) {right = in + tmp;} 01387 else {right = in + DBL_MIN;} 01388 #endif 01389 left = in; 01390 } // ibis::util::eq2range 01391 01395 template <typename Tin> 01396 inline void ibis::util::round_up(const Tin& inval, float& outval) { 01397 // perform the initial rounding 01398 outval = static_cast<float>(inval); 01399 if (static_cast<Tin>(outval) < inval) { 01400 // if the rounded value is less than the input value, compute the 01401 // next value 01402 #if defined(HAVE_NEXTAFTER) 01403 outval = nextafterf(static_cast<float>(inval), FLT_MAX); 01404 #else 01405 float tmp = fabsf(outval) * FLT_EPSILON; 01406 if (tmp > 0.0) outval += tmp; 01407 else outval += FLT_MIN; 01408 #endif 01409 } 01410 } // ibis::util::round_up 01411 01412 // remove all the trailing char 'tail' 01413 inline void ibis::util::removeTail(char* str, char tail) { 01414 if (str != 0 && *str != 0) { 01415 char *tmp = str; 01416 while (*tmp != 0) ++ tmp; 01417 -- tmp; 01418 while (tmp > str && *tmp == tail) { 01419 *tmp = static_cast<char>(0); 01420 -- tmp; 01421 } 01422 } 01423 } // ibis::util::removeTail 01424 01425 // remove the leading and trailing space of the incoming string 01426 inline char* ibis::util::trim(char* str) { 01427 char* head = 0; 01428 if (str == 0) return head; 01429 if (*str == 0) return head; 01430 01431 head = str; 01432 while (*head) { 01433 if (std::isspace(*head)) 01434 ++ head; 01435 else 01436 break; 01437 } 01438 if (*head == 0) 01439 return head; 01440 01441 for (str = head; *str != 0; ++ str); 01442 -- str; 01443 while (str >= head && std::isspace(*str)) { 01444 *str = static_cast<char>(0); 01445 -- str; 01446 } 01447 return head; 01448 } // ibis::util::trim 01449 01457 inline double ibis::util::coarsen(const double in, unsigned prec) { 01458 double ret; 01459 if (prec > 15) { 01460 ret = in; 01461 } 01462 else if (in == 0.0) { 01463 ret = in; 01464 } 01465 else { 01466 ret = fabs(in); 01467 if (ret < DBL_MIN) { // denormalized number --> 0 01468 ret = 0.0; 01469 } 01470 else if (ret < DBL_MAX) { // normal numbers 01471 ret = log10(ret); 01472 if (prec > 0) 01473 -- prec; 01474 const int ixp = static_cast<int>(floor(ret)) - 01475 static_cast<int>(prec); 01476 ret = floor(0.5 + pow(1e1, ret-ixp)); 01477 if (ixp > 0) 01478 ret *= pow(1e1, ixp); 01479 else if (ixp < 0) 01480 ret /= pow(1e1, -ixp); 01481 if (in < 0.0) 01482 ret = -ret; 01483 } 01484 else { 01485 ret = in; 01486 } 01487 } 01488 return ret; 01489 } // ibis::util::coarsen 01490 01492 inline std::ostream& operator<<(std::ostream& out, const ibis::rid_t& rid) { 01493 out << '(' << rid.num.run << ", " << rid.num.event << ')'; 01494 return out; 01495 } 01496 01498 inline std::istream& operator>>(std::istream& is, ibis::rid_t& rid) { 01499 char c = 0; 01500 is >> c; 01501 if (c == '(') { // (runNumber, EventNumber) 01502 is >> rid.num.run >> c; 01503 if (c == ',') 01504 is >> rid.num.event >> c; 01505 else 01506 rid.num.event = 0; 01507 if (c != ')') 01508 is.clear(std::ios::badbit); // forget the erro 01509 } 01510 else { // runNumber, EventNumber 01511 is.putback(c); 01512 is >> rid.num.run >> c; 01513 if (c != ',') // assume space separator 01514 is.putback(c); 01515 is >> rid.num.event; 01516 } 01517 return is; 01518 } 01519 #endif // IBIS_UTIL_H
![]() |