00001
00002
00003
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>
00020 #include <cstring>
00021 #include <stdio.h>
00022
00023 #include <sys/stat.h>
00024
00025
00026 #include <fcntl.h>
00027
00028 #include <map>
00029 #include <string>
00030 #include <limits>
00031 #include <sstream>
00032
00033 #include <float.h>
00034 #include <math.h>
00035 #if !defined(unix) && defined(_WIN32)
00036 #include <windows.h>
00037 #include <io.h>
00038 #include <fcntl.h>
00039 int truncate(const char*, uint32_t);
00040 #include <direct.h>
00041 #include <sys/stat.h>
00042 #define rmdir _rmdir
00043
00044 #else
00045 #include <unistd.h>
00046 #endif
00047
00048
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
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
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
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
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
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
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
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
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
00258 #ifdef max
00259 #undef max
00260 #endif
00261 #ifdef min
00262 #undef min
00263 #endif
00264 #endif
00265
00266
00267
00268
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 {
00285
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
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 }
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;
00374 char* buff;
00375 compStore cvec;
00376
00377 nameList(const nameList&);
00378 nameList& operator=(const nameList&);
00379 };
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 };
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
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 ) {
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 };
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
00652 static pthread_mutex_t mutex;
00653
00654 ioLock(const ioLock&) {};
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) {};
00682 mutexLock(const mutexLock&);
00683 mutexLock& operator=(const mutexLock&);
00684 };
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();
00703 quietLock(const quietLock&);
00704 quietLock& operator=(const quietLock&);
00705 };
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) {};
00725 readLock(const readLock&);
00726 readLock& operator=(const readLock&);
00727 };
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) {};
00750 writeLock(const writeLock&);
00751 writeLock& operator=(const writeLock&);
00752 };
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 };
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&);
00925 sharedInt32& operator=(const sharedInt32&);
00926 };
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&);
01024 sharedInt64& operator=(const sharedInt64&);
01025 };
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();
01046 timer(const timer&);
01047 timer& operator=(const timer&);
01048 };
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 };
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 };
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;
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 };
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;
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 };
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;
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
01223 guardImpl2& operator=(const guardImpl2&);
01224 };
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;
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 };
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 }
01262 }
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 }
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 }
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 }
01343
01347 template <typename Tin>
01348 inline void ibis::util::round_up(const Tin& inval, float& outval) {
01349
01350 outval = static_cast<float>(inval);
01351 if (static_cast<Tin>(outval) < inval) {
01352
01353
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 }
01363
01364
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 }
01376
01377
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 }
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) {
01420 ret = 0.0;
01421 }
01422 else if (ret < DBL_MAX) {
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 }
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 }
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 == '(') {
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);
01473 }
01474 else {
01475 is.putback(c);
01476 is >> rid.num.run >> c;
01477 if (c != ',')
01478 is.putback(c);
01479 is >> rid.num.event;
01480 }
01481 return is;
01482 }
01483 #endif // IBIS_UTIL_H