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
![]() |