00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014 #ifndef STXXL_UTILS_HEADER
00015 #define STXXL_UTILS_HEADER
00016
00017 #include <iostream>
00018 #include <sstream>
00019 #include <algorithm>
00020 #include <vector>
00021 #include <string>
00022 #include <limits>
00023
00024 #include <cassert>
00025 #include <cstdio>
00026 #include <cerrno>
00027 #include <cstring>
00028 #include <cstdlib>
00029 #include <cmath>
00030 #include <sys/types.h>
00031 #include <sys/stat.h>
00032
00033 #ifdef STXXL_BOOST_CONFIG
00034 #include <boost/config.hpp>
00035 #endif
00036
00037 #ifdef STXXL_BOOST_FILESYSTEM
00038 #include <boost/filesystem/operations.hpp>
00039 #endif
00040
00041 #include <stxxl/bits/namespace.h>
00042 #include <stxxl/bits/common/log.h>
00043 #include <stxxl/bits/common/exceptions.h>
00044 #include <stxxl/bits/common/types.h>
00045 #include <stxxl/bits/common/timer.h>
00046
00047
00048 __STXXL_BEGIN_NAMESPACE
00049
00050 template <typename U>
00051 inline void UNUSED(const U &)
00052 { }
00053
00055
00056 #define __STXXL_STRING(x) # x
00057
00058
00059 #define STXXL_MSG(x) \
00060 { std::cout << "[STXXL-MSG] " << x << std::endl << std::flush; \
00061 stxxl::logger::get_instance()->log_stream() << "[STXXL-MSG] " << x << std::endl << std::flush; \
00062 }
00063
00064 #define STXXL_ERRMSG(x) \
00065 { std::cerr << "[STXXL-ERRMSG] " << x << std::endl << std::flush; \
00066 stxxl::logger::get_instance()->errlog_stream() << "[STXXL-ERRMSG] " << x << std::endl << std::flush; \
00067 }
00068
00069
00070 #ifdef STXXL_FORCE_VERBOSE_LEVEL
00071 #undef STXXL_VERBOSE_LEVEL
00072 #define STXXL_VERBOSE_LEVEL STXXL_FORCE_VERBOSE_LEVEL
00073 #endif
00074
00075 #ifndef STXXL_VERBOSE_LEVEL
00076 #define STXXL_VERBOSE_LEVEL -1
00077 #endif
00078
00079
00080
00081
00082
00083 #if STXXL_VERBOSE_LEVEL > -1
00084 #define STXXL_VERBOSE0(x) \
00085 { std::cout << "[STXXL-VERBOSE0] " << x << std::endl << std::flush; \
00086 stxxl::logger::get_instance()->log_stream() << "[STXXL-VERBOSE0] " << x << std::endl << std::flush; \
00087 }
00088 #else
00089 #define STXXL_VERBOSE0(x)
00090 #endif
00091
00092 #if STXXL_VERBOSE_LEVEL > 0
00093 #define STXXL_VERBOSE1(x) \
00094 { std::cout << "[STXXL-VERBOSE1] " << x << std::endl << std::flush; \
00095 stxxl::logger::get_instance()->log_stream() << "[STXXL-VERBOSE1] " << x << std::endl << std::flush; \
00096 }
00097 #else
00098 #define STXXL_VERBOSE1(x)
00099 #endif
00100
00101 #define STXXL_VERBOSE(x) STXXL_VERBOSE1(x)
00102
00103 #if STXXL_VERBOSE_LEVEL > 1
00104 #define STXXL_VERBOSE2(x) \
00105 { std::cout << "[STXXL-VERBOSE2] " << x << std::endl << std::flush; \
00106 stxxl::logger::get_instance()->log_stream() << "[STXXL-VERBOSE2] " << x << std::endl << std::flush; \
00107 }
00108 #else
00109 #define STXXL_VERBOSE2(x)
00110 #endif
00111
00112 #if STXXL_VERBOSE_LEVEL > 2
00113 #define STXXL_VERBOSE3(x) \
00114 { std::cout << "[STXXL-VERBOSE3] " << x << std::endl << std::flush; \
00115 stxxl::logger::get_instance()->log_stream() << "[STXXL-VERBOSE3] " << x << std::endl << std::flush; \
00116 }
00117 #else
00118 #define STXXL_VERBOSE3(x)
00119 #endif
00120
00122
00123 #ifdef BOOST_MSVC
00124 #define STXXL_PRETTY_FUNCTION_NAME __FUNCTION__
00125 #else
00126 #define STXXL_PRETTY_FUNCTION_NAME __PRETTY_FUNCTION__
00127 #endif
00128
00129 #define STXXL_FORMAT_ERROR_MSG(str_, errmsg_) \
00130 std::ostringstream str_; str_ << "Error in " << errmsg_
00131
00132 #define STXXL_THROW(exception_type, location, error_message) \
00133 { \
00134 std::ostringstream msg_; \
00135 msg_ << "Error in " << location << ": " << error_message; \
00136 throw exception_type(msg_.str()); \
00137 }
00138
00139 #define STXXL_THROW2(exception_type, error_message) \
00140 STXXL_THROW(exception_type, "function " << STXXL_PRETTY_FUNCTION_NAME, \
00141 "Info: " << error_message << " " << strerror(errno))
00142
00143 template <typename E>
00144 inline void stxxl_util_function_error(const char * func_name, const char * expr = 0)
00145 {
00146 std::ostringstream str_;
00147 str_ << "Error in function " << func_name << " " << (expr ? expr : strerror(errno));
00148 throw E(str_.str());
00149 }
00150
00151 #define stxxl_function_error(exception_type) \
00152 stxxl::stxxl_util_function_error<exception_type>(STXXL_PRETTY_FUNCTION_NAME)
00153
00154 template <typename E>
00155 inline bool helper_check_success(bool success, const char * func_name, const char * expr = 0)
00156 {
00157 if (!success)
00158 stxxl_util_function_error<E>(func_name, expr);
00159 return success;
00160 }
00161
00162 template <typename E, typename INT>
00163 inline bool helper_check_eq_0(INT res, const char * func_name, const char * expr)
00164 {
00165 return helper_check_success<E>(res == 0, func_name, expr);
00166 }
00167
00168 #define check_pthread_call(expr) \
00169 stxxl::helper_check_eq_0<stxxl::resource_error>(expr, STXXL_PRETTY_FUNCTION_NAME, __STXXL_STRING(expr))
00170
00171 template <typename E, typename INT>
00172 inline bool helper_check_ge_0(INT res, const char * func_name)
00173 {
00174 return helper_check_success<E>(res >= 0, func_name);
00175 }
00176
00177 #define stxxl_check_ge_0(expr, exception_type) \
00178 stxxl::helper_check_ge_0<exception_type>(expr, STXXL_PRETTY_FUNCTION_NAME)
00179
00180 template <typename E, typename INT>
00181 inline bool helper_check_ne_0(INT res, const char * func_name)
00182 {
00183 return helper_check_success<E>(res != 0, func_name);
00184 }
00185
00186 #define stxxl_check_ne_0(expr, exception_type) \
00187 stxxl::helper_check_ne_0<exception_type>(expr, STXXL_PRETTY_FUNCTION_NAME)
00188
00189 #ifdef BOOST_MSVC
00190
00191 #define stxxl_win_lasterror_exit(errmsg, exception_type) \
00192 { \
00193 TCHAR szBuf[80]; \
00194 LPVOID lpMsgBuf; \
00195 DWORD dw = GetLastError(); \
00196 FormatMessage( \
00197 FORMAT_MESSAGE_ALLOCATE_BUFFER | \
00198 FORMAT_MESSAGE_FROM_SYSTEM, \
00199 NULL, \
00200 dw, \
00201 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), \
00202 (LPTSTR)&lpMsgBuf, \
00203 0, NULL); \
00204 std::ostringstream str_; \
00205 str_ << "Error in " << errmsg << ", error code " << dw << ": " << ((char *)lpMsgBuf); \
00206 LocalFree(lpMsgBuf); \
00207 throw exception_type(str_.str()); \
00208 }
00209
00210 #endif
00211
00213
00214 inline double
00215 stxxl_timestamp()
00216 {
00217 return timestamp();
00218 }
00219
00221
00222 inline std::string
00223 stxxl_tmpfilename(std::string dir, std::string prefix)
00224 {
00225
00226 int rnd;
00227 char buffer[1024];
00228 std::string result;
00229
00230 #ifndef STXXL_BOOST_FILESYSTEM
00231 struct stat st;
00232 #endif
00233
00234 do
00235 {
00236 rnd = rand();
00237 sprintf(buffer, "%d", rnd);
00238 result = dir + prefix + buffer;
00239 }
00240 #ifdef STXXL_BOOST_FILESYSTEM
00241 while (boost::filesystem::exists(result));
00242
00243 return result;
00244 #else
00245 while (!lstat(result.c_str(), &st));
00246
00247 if (errno != ENOENT)
00248 stxxl_function_error(io_error);
00249
00250 return result;
00251 #endif
00252 }
00253
00255
00256 inline std::vector<std::string>
00257 split(const std::string & str, const std::string & sep)
00258 {
00259 std::vector<std::string> result;
00260 if (str.empty())
00261 return result;
00262
00263 std::string::size_type CurPos(0), LastPos(0);
00264 while (1)
00265 {
00266 CurPos = str.find(sep, LastPos);
00267 if (CurPos == std::string::npos)
00268 break;
00269
00270 std::string sub =
00271 str.substr(LastPos,
00272 std::string::size_type(CurPos -
00273 LastPos));
00274 if (sub.size())
00275 result.push_back(sub);
00276
00277 LastPos = CurPos + sep.size();
00278 }
00279
00280 std::string sub = str.substr(LastPos);
00281 if (sub.size())
00282 result.push_back(sub);
00283
00284 return result;
00285 }
00286
00288
00289 #define str2int(str) atoi(str.c_str())
00290
00291 inline std::string int2str(int i)
00292 {
00293 char buf[32];
00294 sprintf(buf, "%d", i);
00295 return std::string(buf);
00296 }
00297
00298 inline stxxl::int64 atoint64(const char * s)
00299 {
00300 #ifdef BOOST_MSVC
00301 return _atoi64(s);
00302 #else
00303 return atoll(s);
00304 #endif
00305 }
00306
00308
00309 #define STXXL_MIN(a, b) ((std::min)(a, b))
00310 #define STXXL_MAX(a, b) ((std::max)(a, b))
00311
00312 #define STXXL_L2_SIZE (512 * 1024)
00313
00314 #define div_and_round_up(a, b) ((a) / (b) + !(!((a) % (b))))
00315
00316 #define log2(x) (log(x) / log(2.))
00317
00319
00320
00321
00322 #ifdef HAVE_BUILTIN_EXPECT
00323 #define LIKELY(c) __builtin_expect((c), 1)
00324 #else
00325 #define LIKELY(c) c
00326 #endif
00327
00328 #ifdef HAVE_BUILTIN_EXPECT
00329 #define UNLIKELY(c) __builtin_expect((c), 0)
00330 #else
00331 #define UNLIKELY(c) c
00332 #endif
00333
00335
00336
00337
00338 #ifdef COUNT_WAIT_TIME
00339
00340 #define START_COUNT_WAIT_TIME double count_wait_begin = stxxl_timestamp();
00341 #define END_COUNT_WAIT_TIME stxxl::wait_time_counter += (stxxl_timestamp() - count_wait_begin);
00342
00343 #define reset_io_wait_time() stxxl::wait_time_counter = 0.0;
00344
00345 #define io_wait_time() (stxxl::wait_time_counter)
00346
00347 #else
00348
00349 #define START_COUNT_WAIT_TIME
00350 #define END_COUNT_WAIT_TIME
00351
00352 inline void reset_io_wait_time()
00353 { }
00354
00355 inline double io_wait_time()
00356 {
00357 return -1.0;
00358 }
00359
00360 #endif
00361
00363
00364 inline uint64 longhash1(uint64 key_)
00365 {
00366 key_ += ~(key_ << 32);
00367 key_ ^= (key_ >> 22);
00368 key_ += ~(key_ << 13);
00369 key_ ^= (key_ >> 8);
00370 key_ += (key_ << 3);
00371 key_ ^= (key_ >> 15);
00372 key_ += ~(key_ << 27);
00373 key_ ^= (key_ >> 31);
00374 return key_;
00375 }
00376
00378
00379 template <class _ForwardIter>
00380 bool is_sorted(_ForwardIter __first, _ForwardIter __last)
00381 {
00382 if (__first == __last)
00383 return true;
00384
00385 _ForwardIter __next = __first;
00386 for (++__next; __next != __last; __first = __next, ++__next) {
00387 if (*__next < *__first)
00388 return false;
00389 }
00390
00391 return true;
00392 }
00393
00394 template <class _ForwardIter, class _StrictWeakOrdering>
00395 bool is_sorted(_ForwardIter __first, _ForwardIter __last,
00396 _StrictWeakOrdering __comp)
00397 {
00398 if (__first == __last)
00399 return true;
00400
00401 _ForwardIter __next = __first;
00402 for (++__next; __next != __last; __first = __next, ++__next) {
00403 if (__comp(*__next, *__first))
00404 return false;
00405 }
00406
00407 return true;
00408 }
00409
00411
00412 template <class T>
00413 inline void swap_1D_arrays(T * a, T * b, unsigned_type size)
00414 {
00415 for (unsigned_type i = 0; i < size; ++i)
00416 std::swap(a[i], b[i]);
00417 }
00418
00420
00421 template <class T>
00422 class new_alloc;
00423
00424 template <typename T, typename U>
00425 struct new_alloc_rebind;
00426
00427 template <typename T>
00428 struct new_alloc_rebind<T, T>{
00429 typedef new_alloc<T> other;
00430 };
00431
00432 template <typename T, typename U>
00433 struct new_alloc_rebind {
00434 typedef std::allocator<U> other;
00435 };
00436
00437
00438
00439 template <class T>
00440 class new_alloc {
00441 public:
00442
00443 typedef T value_type;
00444 typedef T * pointer;
00445 typedef const T * const_pointer;
00446 typedef T & reference;
00447 typedef const T & const_reference;
00448 typedef std::size_t size_type;
00449 typedef std::ptrdiff_t difference_type;
00450
00451
00452 template <class U>
00453 struct rebind {
00454 typedef typename new_alloc_rebind<T, U>::other other;
00455 };
00456
00457
00458 pointer address(reference value) const
00459 {
00460 return &value;
00461 }
00462 const_pointer address(const_reference value) const
00463 {
00464 return &value;
00465 }
00466
00467 new_alloc() throw () { }
00468 new_alloc(const new_alloc &) throw () { }
00469 template <class U>
00470 new_alloc(const new_alloc<U> &) throw () { }
00471 ~new_alloc() throw () { }
00472
00473 template <class U>
00474 operator std::allocator<U>()
00475 {
00476 static std::allocator<U> helper_allocator;
00477 return helper_allocator;
00478 }
00479
00480
00481 size_type max_size() const throw ()
00482 {
00483 return (std::numeric_limits<std::size_t>::max) () / sizeof(T);
00484 }
00485
00486
00487 pointer allocate(size_type num, const void * = 0)
00488 {
00489 pointer ret = (pointer)(T::operator new(num * sizeof(T)));
00490 return ret;
00491 }
00492
00493
00494 void construct(pointer p, const T & value)
00495 {
00496
00497 new ((void *)p)T(value);
00498 }
00499
00500
00501 void destroy(pointer p)
00502 {
00503
00504 p->~T();
00505 }
00506
00507
00508 void deallocate(pointer p, size_type )
00509 {
00510 T::operator delete((void *)p);
00511 }
00512 };
00513
00514
00515 template <class T1, class T2>
00516 inline bool operator == (const new_alloc<T1> &,
00517 const new_alloc<T2> &) throw ()
00518 {
00519 return true;
00520 }
00521
00522 template <class T1, class T2>
00523 inline bool operator != (const new_alloc<T1> &,
00524 const new_alloc<T2> &) throw ()
00525 {
00526 return false;
00527 }
00528
00530
00531 inline unsigned_type sort_memory_usage_factor()
00532 {
00533 #if defined(__MCSTL__) && !defined(STXXL_NOT_CONSIDER_SORT_MEMORY_OVERHEAD)
00534 return (mcstl::HEURISTIC::sort_algorithm == mcstl::HEURISTIC::MWMS && mcstl::HEURISTIC::num_threads > 1) ? 2 : 1;
00535 #else
00536 return 1;
00537 #endif
00538 }
00539
00541
00542 #ifdef __MCSTL__
00543 #define __STXXL_FORCE_SEQUENTIAL , mcstl::sequential_tag()
00544 #else
00545 #define __STXXL_FORCE_SEQUENTIAL
00546 #endif
00547
00548 __STXXL_END_NAMESPACE
00549
00550 #endif // !STXXL_UTILS_HEADER