00001
00002
00003
00004 #ifndef IBIS_UTIL_H
00005 #define IBIS_UTIL_H
00010 #if defined(_WIN32) && defined(_MSC_VER) && defined(_DEBUG)
00011 #define _CRTDBG_MAP_ALLOC
00012 #include <stdlib.h>
00013 #include <crtdbg.h>
00014 #elif defined(HAVE_STDLIB_H)
00015 #include <stdlib.h>
00016 #elif defined(unix) || defined(linux) || defined(__APPLE__) || defined(__FreeBSD) || defined(__CYGWIN__)
00017 #include <stdlib.h>
00018 #endif
00019 #include "const.h"
00020
00021 #include <ctype.h>
00022 #include <stdio.h>
00023
00024 #include <sys/stat.h>
00025
00026
00027 #include <fcntl.h>
00028
00029 #include <map>
00030 #include <string>
00031 #include <limits>
00032 #include <sstream>
00033
00034 #include <float.h>
00035 #include <math.h>
00036 #if !defined(unix) && defined(_WIN32)
00037 #include <windows.h>
00038 #include <io.h>
00039 #include <fcntl.h>
00040 int truncate(const char*, uint32_t);
00041 #include <direct.h>
00042 #include <sys/stat.h>
00043 #define rmdir _rmdir
00044
00045 #else
00046 #include <unistd.h>
00047 #endif
00048
00049
00050 #ifndef FASTBIT_MIN_MAP_SIZE
00051 #define FASTBIT_MIN_MAP_SIZE 1048576
00052 #endif
00053
00054 #if ! (defined(HAVE_MMAP) || defined(_MSC_VER))
00055 # if defined(_XOPEN_SOURCE)
00056 # define HAVE_MMAP _XOPEN_SOURCE - 0 >= 500
00057 # elif defined(_POSIX_C_SOURCE)
00058 # define HAVE_MMAP _POSIX_C_SOURCE - 0 >= 0
00059 # else
00060 # define HAVE_MMAP defined(unix)||defined(linux)||defined(__APPLE__)||defined(__CYGWIN__)
00061 # endif
00062 #endif
00063
00064 #if (HAVE_MMAP+0>0) || (defined(_WIN32) && defined(_MSC_VER))
00065 #define HAVE_FILE_MAP 1
00066 #endif
00067
00068 #ifndef DBL_EPSILON
00069 #define DBL_EPSILON 2.2204460492503131e-16
00070 #else
00071
00072 #undef DBL_EPSILON
00073 #define DBL_EPSILON 2.2204460492503131e-16
00074 #endif
00075
00077 #if !defined(HAVE_GCC_ATOMIC32) && defined(WITHOUT_FASTBIT_CONFIG_H)
00078 #if __GNUC__+0 >= 4 && !defined(__CYGWIN__) && !defined(__PATHCC__) && !defined(__APPLE__)
00079 #define HAVE_GCC_ATOMIC32 2
00080 #endif
00081 #endif
00082 #if !defined(HAVE_GCC_ATOMIC64) && defined(WITHOUT_FASTBIT_CONFIG_H)
00083 #if defined(__IA64__) || defined(__x86_64__) || defined(__ppc64__)
00084 #if __GNUC__+0 >= 4 && !defined(__CYGWIN__) && !defined(__PATHCC__) && !defined(__APPLE__)
00085 #define HAVE_GCC_ATOMIC64 2
00086 #endif
00087 #endif
00088 #endif
00089
00091 #if defined(_MSC_VER) && defined(_WIN32)
00092 #ifndef HAVE_WIN_ATOMIC32
00093 #if defined(NTDDI_VERSION) && defined(NTDDI_WIN2K)
00094 #if NTDDI_VERSION >= NTDDI_WIN2K
00095 #define HAVE_WIN_ATOMIC32
00096 #endif
00097 #elif defined(WINVER)
00098 #if WINVER >= 0x0500
00099 #define HAVE_WIN_ATOMIC32
00100 #endif
00101 #endif
00102 #endif
00103 #ifndef HAVE_WIN_ATOMIC64
00104 #if defined(NTDDI_VERSION) && defined(NTDDI_WINVISTA)
00105 #if NTDDI_VERSION >= NTDDI_WINVISTA
00106 #define HAVE_WIN_ATOMIC64
00107 #endif
00108 #elif defined(WINVER)
00109 #if WINVER >= 0x0600
00110 #define HAVE_WIN_ATOMIC64
00111 #endif
00112 #endif
00113 #endif
00114 #endif
00115
00116
00117 #if defined(_MSC_VER) && defined(_WIN32)
00118 #define UnixOpen ::_open
00119 #define UnixClose ::_close
00120 #define UnixRead ::_read
00121 #define UnixWrite ::_write
00122 #define UnixSeek ::_lseek
00123 #define UnixFlush ::_commit
00124 #define UnixSnprintf ::_snprintf
00125 #define UnixStat ::_stat
00126 #define UnixFStat ::_fstat
00127 #define Stat_T struct _stat
00128 #else
00129 #define UnixOpen ::open
00130 #define UnixClose ::close
00131 #define UnixRead ::read
00132 #define UnixWrite ::write
00133 #define UnixSeek ::lseek
00134 #define UnixFlush ::fsync
00135 #define UnixSnprintf ::snprintf
00136 #define UnixStat ::stat
00137 #define UnixFStat ::fstat
00138 #define Stat_T struct stat
00139 #endif
00140
00141
00142 #if defined(O_RDONLY)
00143 #if defined(O_LARGEFILE)
00144 #if defined(O_BINARY)
00145 #define OPEN_READONLY O_RDONLY | O_BINARY | O_LARGEFILE
00146 #else
00147 #define OPEN_READONLY O_RDONLY | O_LARGEFILE
00148 #endif
00149 #elif defined(O_BINARY)
00150 #define OPEN_READONLY O_RDONLY | O_BINARY
00151 #else
00152 #define OPEN_READONLY O_RDONLY
00153 #endif
00154 #elif defined(_O_RDONLY)
00155 #if defined(_O_LARGEFILE)
00156 #define OPEN_READONLY _O_RDONLY | _O_LARGEFILE | _O_BINARY
00157 #else
00158 #define OPEN_READONLY _O_RDONLY | _O_BINARY
00159 #endif
00160 #endif
00161
00162 #if defined(O_WRONLY)
00163 #if defined(O_LARGEFILE)
00164 #if defined(O_BINARY)
00165 #define OPEN_WRITENEW O_WRONLY | O_BINARY | O_CREAT | O_TRUNC | O_LARGEFILE
00166 #else
00167 #define OPEN_WRITENEW O_WRONLY | O_CREAT | O_TRUNC | O_LARGEFILE
00168 #endif
00169 #elif defined(O_BINARY)
00170 #define OPEN_WRITENEW O_WRONLY | O_BINARY | O_CREAT | O_TRUNC
00171 #else
00172 #define OPEN_WRITENEW O_WRONLY | O_CREAT | O_TRUNC
00173 #endif
00174 #elif defined(_O_WRONLY)
00175 #if defined(_O_LARGEFILE)
00176 #define OPEN_WRITENEW _O_WRONLY|_O_CREAT|_O_TRUNC|_O_LARGEFILE|_O_BINARY
00177 #else
00178 #define OPEN_WRITENEW _O_WRONLY|_O_CREAT|_O_TRUNC|_O_BINARY
00179 #endif
00180 #endif
00181
00182 #if defined(O_WRONLY)
00183 #if defined(O_LARGEFILE)
00184 #if defined(O_BINARY)
00185 #define OPEN_WRITEADD O_WRONLY | O_BINARY | O_CREAT | O_LARGEFILE
00186 #else
00187 #define OPEN_WRITEADD O_WRONLY | O_CREAT| O_LARGEFILE
00188 #endif
00189 #elif defined(O_BINARY)
00190 #define OPEN_WRITEADD O_WRONLY | O_BINARY | O_CREAT
00191 #else
00192 #define OPEN_WRITEADD O_WRONLY | O_CREAT
00193 #endif
00194 #elif defined(_O_WRONLY)
00195 #if defined(_O_LARGEFILE)
00196 #define OPEN_WRITEADD _O_WRONLY | _O_CREAT | _O_LARGEFILE | _O_BINARY
00197 #else
00198 #define OPEN_WRITEADD _O_WRONLY | _O_CREAT | _O_BINARY
00199 #endif
00200 #endif
00201
00202 #if defined(O_RDWR)
00203 #if defined(O_LARGEFILE)
00204 #if defined(O_BINARY)
00205 #define OPEN_READWRITE O_RDWR | O_BINARY | O_CREAT | O_LARGEFILE
00206 #else
00207 #define OPEN_READWRITE O_RDWR | O_CREAT | O_LARGEFILE
00208 #endif
00209 #elif defined(O_BINARY)
00210 #define OPEN_READWRITE O_RDWR | O_BINARY | O_CREAT
00211 #else
00212 #define OPEN_READWRITE O_RDWR | O_CREAT
00213 #endif
00214 #elif defined(_O_RDWR)
00215 #if defined(_O_LARGEFILE)
00216 #define OPEN_READWRITE _O_RDWR | _O_CREAT | _O_LARGEFILE | _O_BINARY
00217 #else
00218 #define OPEN_READWRITE _O_RDWR | _O_CREAT | _O_BINARY
00219 #endif
00220 #endif
00221
00222 #if defined(O_WRONLY)
00223 #if defined(O_LARGEFILE)
00224 #if defined(O_BINARY)
00225 #define OPEN_APPENDONLY O_WRONLY | O_BINARY | O_CREAT | O_APPEND | O_LARGEFILE
00226 #else
00227 #define OPEN_APPENDONLY O_WRONLY | O_CREAT | O_APPEND | O_LARGEFILE
00228 #endif
00229 #elif defined(O_BINARY)
00230 #define OPEN_APPENDONLY O_WRONLY | O_BINARY | O_CREAT | O_APPEND
00231 #else
00232 #define OPEN_APPENDONLY O_WRONLY | O_CREAT | O_APPEND
00233 #endif
00234 #elif defined(_O_WRONLY)
00235 #if defined(_O_LARGEFILE)
00236 #define OPEN_APPENDONLY _O_WRONLY | _O_CREAT | _O_APPEND | _O_LARGEFILE | _O_BINARY
00237 #else
00238 #define OPEN_APPENDONLY _O_WRONLY | _O_CREAT | _O_APPEND | _O_BINARY
00239 #endif
00240 #endif
00241
00242 #if defined(_MSC_VER) && defined(_WIN32)
00243 #define OPEN_FILEMODE _S_IREAD | _S_IWRITE
00244 #elif defined(S_IRGRP) && defined(S_IWGRP) && defined(S_IROTH)
00245 #define OPEN_FILEMODE S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH
00246 #else
00247 #define OPEN_FILEMODE S_IRUSR | S_IWUSR
00248 #endif
00249
00250 #if defined(_WIN32) && defined(_MSC_VER)
00251
00252 #ifdef max
00253 #undef max
00254 #endif
00255 #ifdef min
00256 #undef min
00257 #endif
00258 #endif
00259
00260 #define LOGGER(v) \
00261 if (false == (v)) ; else ibis::util::logger(0).buffer()
00262
00263 namespace std {
00264
00265 template <> struct less< char* > {
00266 bool operator()(const char*x, const char*y) const {
00267 return strcmp(x, y) < 0;
00268 }
00269 };
00270
00271
00272 template <> struct less< const char* > {
00273 bool operator()(const char* x, const char* y) const {
00274 return strcmp(x, y) < 0;
00275 }
00276 };
00277
00278 template <> struct less< ibis::rid_t > {
00279 bool operator()(const ibis::rid_t& x, const ibis::rid_t& y) const {
00280 return (x < y);
00281 }
00282 };
00283
00284 template <> struct less< const ibis::rid_t* > {
00285 bool operator()(const ibis::rid_t* x, const ibis::rid_t* y) const {
00286 return (*x < *y);
00287 }
00288 };
00289 }
00290
00291 namespace ibis {
00294 class resource;
00295 class bitvector;
00296 class column;
00297 class fileManager;
00298 class horometer;
00299 class index;
00300 class roster;
00301 class bitvector64;
00302
00303 class bundle;
00304 class colValues;
00305 class whereClause;
00306 class selectClause;
00307
00308
00309 typedef std::vector<colValues*> colList;
00310
00312 FASTBIT_CXX_DLLSPEC ibis::resource& gParameters();
00313
00316 class FASTBIT_CXX_DLLSPEC nameList {
00317 public:
00318 nameList() : cstr(0), buff(0) {};
00319 nameList(const char* str) : cstr(0), buff(0) {select(str);}
00320 ~nameList() {if (cstr) clear();}
00321
00322 bool empty() const {return cstr == 0;}
00323 const char* operator*() const {return cstr;};
00324 uint32_t size() const {return cvec.size();};
00325
00327 void select(const char* str);
00329 void add(const char* str);
00333 uint32_t find(const char* key) const;
00334
00335 const char* operator[](uint32_t i) const {return cvec[i];}
00336 typedef std::vector< const char* >::const_iterator const_iterator;
00337 const_iterator begin() const {return cvec.begin();}
00338 const_iterator end() const {return cvec.end();}
00339
00340 void clear()
00341 {cvec.clear(); delete [] cstr; delete [] buff; buff=0; cstr=0;}
00342
00343 private:
00344 typedef std::vector< const char * > compStore;
00345 char* cstr;
00346 char* buff;
00347 compStore cvec;
00348
00349 nameList(const nameList&);
00350 nameList& operator=(const nameList&);
00351 };
00352
00355 typedef std::map< const char*, part*, lessi > partAssoc;
00356
00358 class bad_alloc : public std::bad_alloc {
00359 public:
00360 bad_alloc(const char *m="unknown") throw() : mesg_(m) {};
00361 virtual ~bad_alloc() throw() {}
00362 virtual const char* what() const throw() {return mesg_;}
00363
00364 private:
00367 const char *mesg_;
00368 };
00369
00371 namespace util {
00373 extern const char* charTable;
00375 extern const short unsigned charIndex[];
00377 extern const char* delimiters;
00384 extern FASTBIT_CXX_DLLSPEC pthread_mutex_t envLock;
00385
00387 inline char* trim(char* str);
00389 inline char* strnewdup(const char* s);
00391 inline char* strnewdup(const char* s, const uint32_t n);
00393 inline void removeTail(char* str, char tail);
00395 FASTBIT_CXX_DLLSPEC char* getString(const char* buf);
00397 FASTBIT_CXX_DLLSPEC void
00398 getString(std::string& str, const char*& buf, const char *delim=0);
00399 const char* getToken(char*& str, const char* tok_chrs);
00400 int readInt(int64_t& val, const char *&str, const char* del);
00401 int readDouble(double& val, const char *&str, const char* del);
00402
00405 void removeDir(const char* name, bool leaveDir=false);
00407 int makeDir(const char*dir);
00410 FASTBIT_CXX_DLLSPEC off_t getFileSize(const char* name);
00413 int copy(const char* to, const char* from);
00414
00416 FASTBIT_CXX_DLLSPEC const char* userName();
00418 uint32_t serialNumber();
00421 void uniformFraction(const long unsigned idx,
00422 long unsigned &denominator,
00423 long unsigned &numerator);
00424 inline double rand();
00425
00428 FASTBIT_CXX_DLLSPEC uint32_t checksum(const char* str, uint32_t sz);
00429 inline uint32_t checksum(uint32_t a, uint32_t b);
00430 inline std::string shortName(const std::string& longname);
00432
00435 void int2string(std::string &str, unsigned val);
00436 void int2string(std::string &str, unsigned v1, unsigned v2);
00437 void int2string(std::string &str, unsigned v1,
00438 unsigned v2, unsigned v3);
00439 void int2string(std::string &str, const std::vector<unsigned>& val);
00441
00444 double incrDouble(const double&);
00445 double decrDouble(const double&);
00446 void eq2range(const double&, double&, double&);
00449 inline double coarsen(const double in, unsigned prec=2);
00452 double compactValue(double left, double right,
00453 double start=0.0);
00454
00457 double compactValue2(double left, double right,
00458 double start=0.0);
00459
00461 void setNaN(double& val);
00462 void setNaN(float& val);
00463
00467 template <typename Tin, typename Tout>
00468 void round_down(const Tin& inval, Tout& outval) {
00469 outval = ((double)std::numeric_limits<Tout>::min() > inval ?
00470 std::numeric_limits<Tout>::min() :
00471 (double)std::numeric_limits<Tout>::max() <= inval ?
00472 std::numeric_limits<Tout>::max() :
00473 static_cast<Tout>(inval));
00474 }
00478 template <typename Tin, typename Tout>
00479 void round_up(const Tin& inval, Tout& outval) {
00480 outval = ((double)std::numeric_limits<Tout>::min() >= inval ?
00481 std::numeric_limits<Tout>::min() :
00482 (double) std::numeric_limits<Tout>::max() < inval ?
00483 std::numeric_limits<Tout>::max() :
00484 static_cast<Tout>(inval) +
00485 ((inval-static_cast<Tin>(static_cast<Tout>(inval))) > 0));
00486 }
00488 template <typename Tin>
00489 void round_up(const Tin& inval, float&);
00491 template <typename Tin>
00492 void round_up(const Tin& inval, double& outval) {
00493 outval = static_cast<double>(inval);
00494 }
00496
00500 FASTBIT_CXX_DLLSPEC void
00501 logMessage(const char* event, const char* fmt, ...);
00508 FASTBIT_CXX_DLLSPEC FILE* getLogFile();
00510 FASTBIT_CXX_DLLSPEC int closeLogFile();
00515 FASTBIT_CXX_DLLSPEC int setLogFileName(const char* filename);
00518 FASTBIT_CXX_DLLSPEC const char* getLogFileName();
00519
00523 FASTBIT_CXX_DLLSPEC bool strMatch(const char* str, const char* pat);
00524
00526 const ibis::bitvector64& outerProduct(const ibis::bitvector& a,
00527 const ibis::bitvector& b,
00528 ibis::bitvector64& c);
00531 const ibis::bitvector64& outerProductUpper(const ibis::bitvector& a,
00532 const ibis::bitvector& b,
00533 ibis::bitvector64& c);
00534
00536 long intersect(const std::vector<ibis::bitvector> &bits1,
00537 const std::vector<ibis::bitvector> &bits2,
00538 std::vector<ibis::bitvector> &res);
00540 long intersect(const std::vector<ibis::bitvector> &bits1,
00541 const std::vector<ibis::bitvector> &bits2,
00542 const std::vector<ibis::bitvector> &bits3,
00543 std::vector<ibis::bitvector> &res);
00545 void clean(std::vector<ibis::bitvector*> &bv) throw();
00547 void clean(ibis::partList &pl) throw();
00549 void getLocalTime(char *str);
00551 void getGMTime(char *str);
00552 void secondsToString(const time_t, char *str);
00553
00554 #if defined(WIN32) && ! defined(__CYGWIN__)
00555 char* getpass_r(const char *prompt, char *buffer, uint32_t buflen);
00556 char* getpass(const char* prompt);
00557 #else
00558 inline char *itoa(int value, char *str, int ) {
00559 sprintf(str,"%d",value);
00560 return str;
00561 }
00562 #endif
00563
00572 class FASTBIT_CXX_DLLSPEC logger {
00573 public:
00575 logger(int blanks=0);
00577 ~logger();
00579 std::ostream& buffer() {return mybuffer;}
00580
00581 protected:
00583 std::ostringstream mybuffer;
00584
00585 private:
00586 logger(const logger&);
00587 logger& operator=(const logger&);
00588 };
00589
00592 class ioLock {
00593 public:
00594 ioLock() {
00595 if (0 != pthread_mutex_lock(&mutex))
00596 throw "ioLock failed to obtain a lock";
00597 }
00598 ~ioLock() {
00599 (void) pthread_mutex_unlock(&mutex);
00600 }
00601 private:
00602
00603 static pthread_mutex_t mutex;
00604
00605 ioLock(const ioLock&) {};
00606 ioLock& operator=(const ioLock&);
00607 };
00608
00610 class mutexLock {
00611 public:
00612 mutexLock(pthread_mutex_t* lk, const char* m)
00613 : mesg(m), lock(lk) {
00614 LOGGER(ibis::gVerbose > 10)
00615 << "util::mutexLock -- acquiring lock (" << lock
00616 << ") for " << mesg;
00617 if (0 != pthread_mutex_lock(lock)) {
00618 throw "mutexLock failed to obtain a lock";
00619 }
00620 }
00621 ~mutexLock() {
00622 LOGGER(ibis::gVerbose > 10)
00623 << "util::mutexLock -- releasing lock (" << lock
00624 << ") for " << mesg;
00625 (void) pthread_mutex_unlock(lock);
00626 }
00627
00628 private:
00629 const char *mesg;
00630 pthread_mutex_t *lock;
00631
00632 mutexLock() : mesg(0), lock(0) {};
00633 mutexLock(const mutexLock&);
00634 mutexLock& operator=(const mutexLock&);
00635 };
00636
00640 class quietLock {
00641 public:
00642 quietLock(pthread_mutex_t *lk) : lock(lk) {
00643 if (0 != pthread_mutex_lock(lock))
00644 throw "quietLock failed to obtain a mutex lock";
00645 }
00646 ~quietLock() {
00647 (void) pthread_mutex_unlock(lock);
00648 }
00649
00650 private:
00651 pthread_mutex_t *lock;
00652
00653 quietLock();
00654 quietLock(const quietLock&);
00655 quietLock& operator=(const quietLock&);
00656 };
00657
00659 class readLock {
00660 public:
00661 readLock(pthread_rwlock_t* lk, const char* m)
00662 : mesg(m), lock(lk) {
00663 if (0 != pthread_rwlock_rdlock(lock)) {
00664 throw "readLock failed to obtain a lock";
00665 }
00666 }
00667 ~readLock() {
00668 (void) pthread_rwlock_unlock(lock);
00669 }
00670
00671 private:
00672 const char *mesg;
00673 pthread_rwlock_t *lock;
00674
00675 readLock() : mesg(0), lock(0) {};
00676 readLock(const readLock&);
00677 readLock& operator=(const readLock&);
00678 };
00679
00681 class writeLock {
00682 public:
00683 writeLock(pthread_rwlock_t* lk, const char* m)
00684 : mesg(m), lock(lk) {
00685 if (0 != pthread_rwlock_wrlock(lock)) {
00686 throw "writeLock failed to obtain a lock";
00687 }
00688 }
00689 ~writeLock() {
00690 int ierr = pthread_rwlock_unlock(lock);
00691 if (ierr != 0) {
00692 throw "writeLock failed to release the lock";
00693 }
00694 }
00695
00696 private:
00697 const char *mesg;
00698 pthread_rwlock_t *lock;
00699
00700 writeLock() : mesg(0), lock(0) {};
00701 writeLock(const writeLock&);
00702 writeLock& operator=(const writeLock&);
00703 };
00704
00711 class FASTBIT_CXX_DLLSPEC counter {
00712 public:
00713 ~counter() {
00714 #if defined(HAVE_GCC_ATOMIC32)
00715 #elif defined(HAVE_WIN_ATOMIC32)
00716 #else
00717 (void)pthread_mutex_destroy(&lock_);
00718 #endif
00719 }
00720 counter() : count_(0) {
00721 #if defined(HAVE_GCC_ATOMIC32)
00722 #elif defined(HAVE_WIN_ATOMIC32)
00723 #else
00724 if (0 != pthread_mutex_init(&lock_, 0))
00725 throw ibis::bad_alloc
00726 ("ibis::util::counter failed to initialize mutex lock");
00727 #endif
00728 }
00729
00731 uint32_t operator()() {
00732 #if defined(HAVE_GCC_ATOMIC32)
00733 return __sync_fetch_and_add(&count_, 1);
00734 #elif defined(HAVE_WIN_ATOMIC32)
00735 return InterlockedIncrement((volatile long *)&count_)-1;
00736 #else
00737 ibis::util::quietLock lck(&lock_);
00738 uint32_t ret = count_;
00739 ++ count_;
00740 return ret;
00741 #endif
00742 }
00744 void reset() {
00745 #if defined(HAVE_GCC_ATOMIC32)
00746 (void) __sync_fetch_and_sub(&count_, count_);
00747 #elif defined(HAVE_WIN_ATOMIC32)
00748 (void) InterlockedExchange((volatile long *)&count_, 0);
00749 #else
00750 ibis::util::quietLock lck(&lock_);
00751 count_ = 0;
00752 #endif
00753 }
00755 uint32_t value() const {
00756 return count_;
00757 }
00758
00759 private:
00760 #if defined(HAVE_GCC_ATOMIC32)
00761 #elif defined(HAVE_WIN_ATOMIC32)
00762 #else
00763 mutable pthread_mutex_t lock_;
00764 #endif
00765 volatile uint32_t count_;
00766
00768 counter(const counter&);
00770 counter& operator=(const counter&);
00771 };
00772
00787 class FASTBIT_CXX_DLLSPEC sharedInt32 {
00788 public:
00789 sharedInt32() : val_(0) {
00790 #if defined(HAVE_GCC_ATOMIC32)
00791 #elif defined(HAVE_WIN_ATOMIC32)
00792 #else
00793 if (pthread_mutex_init(&mytex, 0) != 0)
00794 throw "pthread_mutex_init failed for sharedInt";
00795 #endif
00796 }
00797
00798 ~sharedInt32() {
00799 #if defined(HAVE_GCC_ATOMIC32)
00800 #elif defined(HAVE_WIN_ATOMIC32)
00801 #else
00802 (void)pthread_mutex_destroy(&mytex);
00803 #endif
00804 }
00805
00807 uint32_t operator()() const {return val_;}
00808
00810 uint32_t operator++() {
00811 #if defined(HAVE_GCC_ATOMIC32)
00812 return __sync_add_and_fetch(&val_, 1);
00813 #elif defined(HAVE_WIN_ATOMIC32)
00814 return InterlockedIncrement((volatile long *)&val_);
00815 #else
00816 ibis::util::quietLock lock(&mytex);
00817 ++ val_;
00818 return val_;
00819 #endif
00820 }
00821
00823 uint32_t operator--() {
00824 #if defined(HAVE_GCC_ATOMIC32)
00825 return __sync_add_and_fetch(&val_, -1);
00826 #elif defined(HAVE_WIN_ATOMIC32)
00827 return InterlockedDecrement((volatile long *)&val_);
00828 #else
00829 ibis::util::quietLock lock(&mytex);
00830 -- val_;
00831 return val_;
00832 #endif
00833 }
00834
00836 void operator+=(const uint32_t rhs) {
00837 #if defined(HAVE_GCC_ATOMIC32)
00838 (void) __sync_add_and_fetch(&val_, rhs);
00839 #elif defined(HAVE_WIN_ATOMIC32)
00840 (void) InterlockedExchangeAdd((volatile long *)&val_, rhs);
00841 #else
00842 ibis::util::quietLock lock(&mytex);
00843 val_ += rhs;
00844 #endif
00845 }
00846
00848 void operator-=(const uint32_t rhs) {
00849 #if defined(HAVE_GCC_ATOMIC32)
00850 (void) __sync_sub_and_fetch(&val_, rhs);
00851 #elif defined(HAVE_WIN_ATOMIC32)
00852 (void) InterlockedExchangeAdd((volatile long *)&val_,
00853 -(long)rhs);
00854 #else
00855 ibis::util::quietLock lock(&mytex);
00856 val_ -= rhs;
00857 #endif
00858 }
00859
00861 void swap(sharedInt32 &rhs) {
00862 uint32_t tmp = rhs.val_;
00863 rhs.val_ = val_;
00864 val_ = tmp;
00865 }
00866
00867 private:
00868 uint32_t volatile val_;
00869 #if defined(HAVE_GCC_ATOMIC32)
00870 #elif defined(HAVE_WIN_ATOMIC32)
00871 #else
00872 pthread_mutex_t mytex;
00873 #endif
00874
00875 sharedInt32(const sharedInt32&);
00876 sharedInt32& operator=(const sharedInt32&);
00877 };
00878
00885 class sharedInt64 {
00886 public:
00887 sharedInt64() : val_(0) {
00888 #if defined(HAVE_GCC_ATOMIC64)
00889 #elif defined(HAVE_WIN_ATOMIC64)
00890 #else
00891 if (pthread_mutex_init(&mytex, 0) != 0)
00892 throw "pthread_mutex_init failed for sharedInt";
00893 #endif
00894 }
00895
00896 ~sharedInt64() {
00897 #if defined(HAVE_GCC_ATOMIC64)
00898 #elif defined(HAVE_WIN_ATOMIC64)
00899 #else
00900 (void)pthread_mutex_destroy(&mytex);
00901 #endif
00902 }
00903
00905 uint64_t operator()() const {return val_;}
00906
00908 uint64_t operator++() {
00909 #if defined(HAVE_GCC_ATOMIC64)
00910 return __sync_add_and_fetch(&val_, 1);
00911 #elif defined(HAVE_WIN_ATOMIC64)
00912 return InterlockedIncrement64((volatile LONGLONG *)&val_);
00913 #else
00914 ibis::util::quietLock lock(&mytex);
00915 ++ val_;
00916 return val_;
00917 #endif
00918 }
00919
00921 uint64_t operator--() {
00922 #if defined(HAVE_GCC_ATOMIC64)
00923 return __sync_add_and_fetch(&val_, -1);
00924 #elif defined(HAVE_WIN_ATOMIC64)
00925 return InterlockedDecrement64((volatile LONGLONG *)&val_);
00926 #else
00927 ibis::util::quietLock lock(&mytex);
00928 -- val_;
00929 return val_;
00930 #endif
00931 }
00932
00934 void operator+=(const uint64_t rhs) {
00935 #if defined(HAVE_GCC_ATOMIC64)
00936 (void) __sync_add_and_fetch(&val_, rhs);
00937 #elif defined(HAVE_WIN_ATOMIC64)
00938 (void) InterlockedExchangeAdd64((volatile LONGLONG *)&val_,
00939 rhs);
00940 #else
00941 ibis::util::quietLock lock(&mytex);
00942 val_ += rhs;
00943 #endif
00944 }
00945
00947 void operator-=(const uint64_t rhs) {
00948 #if defined(HAVE_GCC_ATOMIC64)
00949 (void) __sync_sub_and_fetch(&val_, rhs);
00950 #elif defined(HAVE_WIN_ATOMIC64)
00951 (void) InterlockedExchangeAdd64((volatile LONGLONG *)&val_,
00952 -(long)rhs);
00953 #else
00954 ibis::util::quietLock lock(&mytex);
00955 val_ -= rhs;
00956 #endif
00957 }
00958
00960 void swap(sharedInt64 &rhs) {
00961 uint64_t tmp = rhs.val_;
00962 rhs.val_ = val_;
00963 val_ = tmp;
00964 }
00965
00966 private:
00967 uint64_t volatile val_;
00968 #if defined(HAVE_GCC_ATOMIC64)
00969 #elif defined(HAVE_WIN_ATOMIC64)
00970 #else
00971 pthread_mutex_t mytex;
00972 #endif
00973
00974 sharedInt64(const sharedInt64&);
00975 sharedInt64& operator=(const sharedInt64&);
00976 };
00977
00987 class timer {
00988 public:
00989 explicit timer(const char* msg, int lvl=1);
00990 ~timer();
00991
00992 private:
00993 ibis::horometer *chrono_;
00994 std::string mesg_;
00995
00996 timer();
00997 timer(const timer&);
00998 timer& operator=(const timer&);
00999 };
01000
01003 class guardBase {
01004 public:
01007 void dismiss() const {done_ = true;}
01008
01009 protected:
01010 mutable volatile bool done_;
01011
01012 ~guardBase() {};
01013 guardBase() : done_(false) {};
01014
01015 guardBase(const guardBase& rhs) : done_(rhs.done_) {
01016 rhs.dismiss();
01017 }
01018
01020 template <typename T>
01021 static void cleanup(T& task) throw () {
01022 if (task.done_)
01023 return;
01024
01025 try {
01026 task.execute();
01027 }
01028 catch (const std::exception& e) {
01029 LOGGER(ibis::gVerbose > 1)
01030 << " ... caught a std::exception (" << e.what()
01031 << ") in util::gard";
01032 }
01033 catch (const char* s) {
01034 LOGGER(ibis::gVerbose > 1)
01035 << " ... caught a string exception (" << s
01036 << ") in util::guard";
01037 }
01038 catch (...) {
01039 LOGGER(ibis::gVerbose > 1)
01040 << " ... caught a unknown exception in util::guard";
01041 }
01042 task.done_ = true;
01043 }
01044 };
01045
01052 typedef const guardBase& guard;
01053
01056 template <typename F>
01057 class guardImpl0 : public guardBase {
01058 public:
01059 static guardImpl0<F> makeGuard(F f) {
01060 return guardImpl0<F>(f);
01061 }
01062
01064 ~guardImpl0() {cleanup(*this);}
01065
01066 protected:
01067 friend class guardBase;
01068 void execute() {fun_();}
01069
01071 explicit guardImpl0(F f) : fun_(f) {}
01072
01073 private:
01075 F fun_;
01076
01077 guardImpl0();
01078
01079 guardImpl0& operator=(const guardImpl0&);
01080 };
01081
01082 template <typename F>
01083 inline guardImpl0<F> makeGuard(F f) {
01084 return guardImpl0<F>::makeGuard(f);
01085 }
01086
01089 template <typename F, typename A>
01090 class guardImpl1 : public guardBase {
01091 public:
01092 static guardImpl1<F, A> makeGuard(F f, A a) {
01093 return guardImpl1<F, A>(f, a);
01094 }
01095
01097 ~guardImpl1() {cleanup(*this);}
01098
01099 protected:
01100 friend class guardBase;
01101 void execute() {fun_(arg_);}
01102
01104 explicit guardImpl1(F f, A a) : fun_(f), arg_(a) {}
01105
01106 private:
01108 F fun_;
01110 A arg_;
01111
01112 guardImpl1();
01113
01114 guardImpl1& operator=(const guardImpl1&);
01115 };
01116
01117 template <typename F, typename A>
01118 inline guardImpl1<F, A> makeGuard(F f, A a) {
01119 return guardImpl1<F, A>::makeGuard(f, a);
01120 }
01121 }
01122 }
01123
01124 #if defined(WIN32) && ! defined(__CYGWIN__)
01125 char* getpass(const char* prompt);
01126 #endif
01127
01131 inline double ibis::util::rand() {
01134 static uint32_t seed = 1;
01135 static const uint32_t alpha = 69069;
01136 static const double scale = ::pow(0.5, 32);
01137 seed = static_cast<uint32_t>(seed * alpha);
01138 return(scale * seed);
01139 }
01140
01142 inline uint32_t ibis::util::checksum(uint32_t a, uint32_t b) {
01143 uint32_t a0 = (a >> 16);
01144 uint32_t a1 = (a & 0xFFFF);
01145 uint32_t b0 = (b >> 16);
01146 uint32_t b1 = (b & 0xFFFF);
01147 return ((((a0<<2)+a1*3+(b0<<1)+b1) << 16) | ((a0+a1+b0+b1) & 0xFFFF));
01148 }
01149
01157 inline double ibis::util::incrDouble(const double& in) {
01158 #if defined(HAVE_NEXTAFTER)
01159 return nextafter(in, DBL_MAX);
01160 #elif defined(_MSC_VER) && defined(_WIN32)
01161 return _nextafter(in, DBL_MAX);
01162 #else
01163 double tmp = fabs(in) * DBL_EPSILON;
01164 if (tmp > 0.0) tmp += in;
01165 else tmp = in + DBL_MIN;
01166 return tmp;
01167 #endif
01168 }
01169
01172 inline double ibis::util::decrDouble(const double& in) {
01173 #if defined(HAVE_NEXTAFTER)
01174 return nextafter(in, -DBL_MAX);
01175 #elif defined(_MSC_VER) && defined(_WIN32)
01176 return _nextafter(in, -DBL_MAX);
01177 #else
01178 double tmp = fabs(in) * DBL_EPSILON;
01179 if (tmp > 0.0) tmp = in - tmp;
01180 else tmp = in - DBL_MIN;
01181 return tmp;
01182 #endif
01183 }
01184
01189 inline void ibis::util::eq2range(const double& in,
01190 double& left, double& right) {
01191 #if defined(HAVE_NEXTAFTER)
01192 right = nextafter(in, DBL_MAX);
01193 #elif defined(_MSC_VER) && defined(_WIN32)
01194 right = _nextafter(in, DBL_MAX);
01195 #else
01196 double tmp = fabs(in) * DBL_EPSILON;
01197 if (tmp > 0.0) {right = in + tmp;}
01198 else {right = in + DBL_MIN;}
01199 #endif
01200 left = in;
01201 }
01202
01206 template <typename Tin>
01207 inline void ibis::util::round_up(const Tin& inval, float& outval) {
01208
01209 outval = static_cast<float>(inval);
01210 if (static_cast<Tin>(outval) < inval) {
01211
01212
01213 #if defined(HAVE_NEXTAFTER)
01214 outval = nextafterf(static_cast<float>(inval), FLT_MAX);
01215 #else
01216 float tmp = fabsf(outval) * FLT_EPSILON;
01217 if (tmp > 0.0) outval += tmp;
01218 else outval += FLT_MIN;
01219 #endif
01220 }
01221 }
01222
01225 inline char* ibis::util::strnewdup(const char* s) {
01226 char* str = 0;
01227 if (s!=0 && *s!=static_cast<char>(0)) {
01228 str = new char[strlen(s)+1];
01229 strcpy(str, s);
01230 }
01231 return str;
01232 }
01233
01234 inline char* ibis::util::strnewdup(const char* s, const uint32_t n) {
01235 char* str = 0;
01236 if (n > 0 && s != 0 && *s != static_cast<char>(0)) {
01237 uint32_t len = strlen(s);
01238 if (n < len)
01239 len = n;
01240 str = new char[len+1];
01241 strncpy(str, s, len);
01242 str[len] = 0;
01243 }
01244 return str;
01245 }
01246
01247
01248 inline void ibis::util::removeTail(char* str, char tail) {
01249 uint32_t j = strlen(str);
01250 while (j > 0 && str[j-1] == tail) {
01251 -- j;
01252 str[j] = static_cast<char>(0);
01253 }
01254 }
01255
01256
01257 inline char* ibis::util::trim(char* str) {
01258 char* head = 0;
01259 if (str == 0) return head;
01260 if (*str == 0) return head;
01261
01262 head = str;
01263 char* tail = str + strlen(str) - 1;
01264 while (*head) {
01265 if (isspace(*head))
01266 ++head;
01267 else
01268 break;
01269 }
01270 while (tail>=head && isspace(*tail)) {
01271 *tail=static_cast<char>(0);
01272 --tail;
01273 }
01274 return head;
01275 }
01276
01284 inline double ibis::util::coarsen(const double in, unsigned prec) {
01285 double ret;
01286 if (prec > 15) {
01287 ret = in;
01288 }
01289 else if (in == 0.0) {
01290 ret = in;
01291 }
01292 else {
01293 ret = fabs(in);
01294 if (ret < 1e-300) {
01295 ret = 0.0;
01296 }
01297 else if (ret < 1e300) {
01298 ret = log10(ret);
01299 if (prec > 0)
01300 -- prec;
01301 const int ixp = static_cast<int>(ret) - static_cast<int>(prec);
01302 ret = floor(0.5 + pow(1e1, ret-ixp));
01303 if (ixp > 0)
01304 ret *= pow(1e1, ixp);
01305 else if (ixp < 0)
01306 ret /= pow(1e1, -ixp);
01307 if (in < 0.0)
01308 ret = -ret;
01309 }
01310 else {
01311 ret = in;
01312 }
01313 }
01314 return ret;
01315 }
01316
01317 inline std::string ibis::util::shortName(const std::string& de) {
01318 std::string tn;
01319 uint32_t tmp = ibis::util::checksum(de.c_str(), de.size());
01320 ibis::util::int2string(tn, tmp);
01321 std::swap(tn[0], tn[5]);
01322 if (! isalpha(tn[0]))
01323 tn[0] = 'A' + (tn[0] % 26);
01324 return tn;
01325 }
01326
01328 inline std::ostream& operator<<(std::ostream& out, const ibis::rid_t& rid) {
01329 out << '(' << rid.num.run << ", " << rid.num.event << ')';
01330 return out;
01331 }
01332
01334 inline std::istream& operator>>(std::istream& is, ibis::rid_t& rid) {
01335 char c = 0;
01336 is >> c;
01337 if (c == '(') {
01338 is >> rid.num.run >> c;
01339 if (c == ',')
01340 is >> rid.num.event >> c;
01341 else
01342 rid.num.event = 0;
01343 if (c != ')')
01344 is.clear(std::ios::badbit);
01345 }
01346 else {
01347 is.putback(c);
01348 is >> rid.num.run >> c;
01349 if (c != ',')
01350 is.putback(c);
01351 is >> rid.num.event;
01352 }
01353 return is;
01354 }
01355 #endif // IBIS_UTIL_H