casa
$Rev:20696$
|
00001 /* 00002 * UtilJ.h 00003 * 00004 * Created on: Nov 4, 2010 00005 * Author: jjacobs 00006 */ 00007 00008 #ifndef UTILJ_H_ 00009 #define UTILJ_H_ 00010 00011 // Casa Includes 00012 00013 #include <casa/aips.h> 00014 #include <casa/BasicSL/String.h> 00015 #include <casa/Exceptions/Error.h> 00016 00017 // C++ and System Includes 00018 00019 #include <cassert> 00020 #include <cstdarg> 00021 #include <cstdlib> 00022 #include <sys/time.h> 00023 #include <sys/resource.h> 00024 // STL Includes 00025 #include <algorithm> 00026 #include <functional> 00027 #include <iterator> 00028 #include <map> 00029 #include <set> 00030 #include <vector> 00031 00032 // The Assert macro is an alias to the standard assert macro when NDEBUG is defined. When 00033 // NDEBUG is not defined (release build) then a throw is used to report the error. 00034 00035 #ifdef NDEBUG 00036 #define Assert(c) assert (c) 00037 #else 00038 #define Assert(c) { utilj::throwIf (! (c), "Assertion failed: " #c, __FILE__, __LINE__, __PRETTY_FUNCTION__); } 00039 #endif 00040 00041 #define AssertAlways(c) { throwIf (! (c), "Assertion failed: " #c, __FILE__, __LINE__, __PRETTY_FUNCTION__); } 00042 00043 #ifdef __GNUC__ 00044 #define DEPRECATED(func) func __attribute__ ((deprecated)); func 00045 #elif defined(_MSC_VER) 00046 #define DEPRECATED(func) __declspec(deprecated) func 00047 #else 00048 00049 #define DEPRECATED(func) func 00050 #endif 00051 00052 #ifdef __GNUC__ 00053 #define DEPRECATED_METHOD(comment) __attribute__ ((deprecated)) 00054 #else 00055 00056 #define DEPRECATED_METHOD(comment) 00057 #endif 00058 00059 00060 #if defined (NDEBUG) 00061 # define Throw(m) \ 00062 { AipsError anAipsError ((m), __FILE__, __LINE__);\ 00063 toStdError (anAipsError.what());\ 00064 throw anAipsError; } 00065 #else 00066 # define Throw(m) throw AipsError ((m), __FILE__, __LINE__) 00067 #endif 00068 00069 #define ThrowIf(c,m) {if (c) {casa::utilj::throwIf ((c), (m), __FILE__, __LINE__, __PRETTY_FUNCTION__);}} 00070 00071 #define ThrowIfError(c,m) {if (c) {casa::utilj::throwIfError ((c), (m), __FILE__, __LINE__, __PRETTY_FUNCTION__);}} 00072 00073 #define Rethrow(e,m) {throw casa::utilj::repackageAipsError ((e),(m),__FILE__,__LINE__, __PRETTY_FUNCTION__);} 00074 00075 namespace casa { 00076 00077 class String; 00078 00079 namespace utilj { 00080 00081 class AipsErrorTrace : public AipsError { 00082 00083 public: 00084 00085 AipsErrorTrace ( const String &msg, const String &filename, uInt lineNumber, 00086 Category c = GENERAL); 00087 00088 }; 00089 00090 class Strings : public std::vector<String> {}; 00091 00092 //template <typename Element, typename Container> 00093 //Bool 00094 //contains (const Element & e, const Container & c) 00095 //{ 00096 // return c.find(e) != c.end(); 00097 //} 00098 00099 00100 template <typename Container> 00101 Bool 00102 containsKey (const typename Container::key_type & key, 00103 const Container & container) 00104 { 00105 return container.find(key) != container.end(); 00106 } 00107 00108 template <typename Container> 00109 Bool 00110 contains (const typename Container::value_type & e, 00111 const Container & c) 00112 { 00113 // For set and map use containsKey; will work for set but 00114 // use with map requires specifying a pair as the first argument 00115 00116 return std::find(c.begin(), c.end(), e) != c.end(); 00117 } 00118 00119 template <typename F, typename S> 00120 F & first (std::pair<F,S> & pair) { return pair.first;} 00121 00122 template <typename F, typename S> 00123 const F & first (const std::pair<F,S> & pair) { return pair.first;} 00124 00125 template <typename F, typename S> 00126 class FirstFunctor : public std::unary_function<std::pair<F,S>, F>{ 00127 public: 00128 F & operator() (std::pair<F,S> & p) { return p.first; } 00129 const F & operator() (const std::pair<F,S> & p) { return p.first; } 00130 }; 00131 00132 template <typename Container, typename Element> 00133 Container 00134 fillContainer (Element sentinel, ...) 00135 { 00136 using namespace std; 00137 00138 Container container; 00139 00140 va_list vaList; 00141 va_start (vaList, sentinel); 00142 00143 Element e = va_arg (vaList, Element); 00144 00145 insert_iterator<Container> i = inserter (container, container.begin()); 00146 00147 while (e != sentinel){ 00148 00149 * i ++ = e; 00150 00151 e = va_arg (vaList, Element); 00152 } 00153 00154 va_end (vaList); 00155 00156 return container; 00157 } 00158 00159 template <typename F, typename S> 00160 FirstFunctor<F,S> firstFunctor () { return FirstFunctor<F,S> ();} 00161 00162 00163 String format (const char * formatString, ...); 00164 String formatV (const String & formatString, va_list vaList); 00165 00166 template<typename T> 00167 T 00168 getEnv (const String & name, const T & defaultValue) 00169 { 00170 char * value = getenv (name.c_str()); 00171 00172 if (value == NULL){ 00173 return defaultValue; 00174 } 00175 else{ 00176 return T (value); 00177 } 00178 } 00179 00180 Bool 00181 getEnv (const String & name, const Bool & defaultValue); 00182 00183 Int 00184 getEnv (const String & name, const Int & defaultValue); 00185 00186 00187 String getTimestamp (); 00188 00189 Bool isEnvDefined (const String & name); 00190 00191 std::vector<String> split (const String & string, const String & splitter, 00192 Bool ignoreConsecutiveSplitters = False); 00193 00194 template <typename Itr> 00195 String 00196 join (Itr begin, Itr end, const String & delimiter) 00197 { 00198 String result; 00199 Itr i = begin; 00200 00201 if (i != end){ 00202 00203 result = * i ++; 00204 00205 for (; i != end; i++){ 00206 result += delimiter + * i; 00207 } 00208 } 00209 00210 return result; 00211 } 00212 00213 template <typename T> 00214 String 00215 join (const T & strings, const String & delimiter) 00216 { 00217 return join (strings.begin(), strings.end(), delimiter); 00218 } 00219 00220 template <typename Itr, typename F> 00221 String 00222 join (Itr begin, Itr end, F f, const String & delimiter) 00223 { 00224 String result; 00225 Itr i = begin; 00226 00227 if (i != end){ 00228 00229 result = f(* i); 00230 ++ i; 00231 00232 for (; i != end; i++){ 00233 result += delimiter + f (* i); 00234 } 00235 } 00236 00237 return result; 00238 } 00239 00240 template <typename K, typename V> 00241 std::vector<K> 00242 mapKeys (const std::map<K,V> & aMap) 00243 { 00244 std::vector<K> result; 00245 00246 std::transform (aMap.begin(), aMap.end(), back_inserter (result), firstFunctor<K,V>()); 00247 00248 return result; 00249 } 00250 00251 AipsError repackageAipsError (AipsError & error, const String & message, const String & file, 00252 Int line, const String & func); 00253 00254 template <typename F, typename S> 00255 F & second (std::pair<F,S> & pair) { return pair.second;} 00256 00257 template <typename F, typename S> 00258 const F & second (const std::pair<F,S> & pair) { return pair.second;} 00259 00260 template <typename F, typename S> 00261 class SecondFunctor : public std::unary_function<std::pair<F,S>, F>{ 00262 public: 00263 S & operator() (std::pair<F,S> & p) { return p.second; } 00264 }; 00265 00266 template <typename F, typename S> 00267 SecondFunctor<F,S> secondFunctor () { return SecondFunctor<F,S> ();} 00268 00269 template <typename K, typename V> 00270 std::vector<V> 00271 mapValues (const std::map<K,V> & aMap) 00272 { 00273 std::vector<K> result (aMap.size()); 00274 00275 std::transform (aMap.begin(), aMap.end(), back_inserter (result), second<K,V>); 00276 00277 return result; 00278 } 00279 00280 void printBacktrace (ostream & os, const String & prefix = ""); 00281 00282 00283 00284 void sleepMs (Int milliseconds); 00285 void toStdError (const String & m, const String & prefix = "*E* "); 00286 void throwIf (Bool condition, const String & message, const String & file, 00287 Int line, const String & func = String()); 00288 void throwIfError (Int errorCode, const String & prefix, const String & file, 00289 Int line, const String & func = String()); 00290 00291 template <typename It, typename Obj> 00292 string 00293 containerToString (It begin, It end, String (Obj::* func) () const, const String & delimiter = ",", 00294 const String & wrapper = "") 00295 { 00296 String result; 00297 String d = ""; 00298 00299 for (It i = begin; i != end; i++){ 00300 result += d + wrapper + ((* i) .* func) () + wrapper; 00301 d = delimiter; 00302 } 00303 00304 return result; 00305 } 00306 00307 class MemoryStatistics { 00308 00309 public: 00310 00311 MemoryStatistics (); 00312 00313 void update (); // call to get the latest stats loaded 00314 double getRssInMB () const; // get resident set size 00315 int64_t getRssInBytes () const; 00316 00317 double getVmInMB () const; // get the Virtual memory size 00318 int64_t getVmInBytes () const; 00319 00320 private: 00321 00322 double bytesPerMb_p; 00323 string filename_p; 00324 int pageSize_p; 00325 int64_t rssPages_p; // in pages 00326 int64_t vmPages_p; // in pages 00327 }; 00328 00329 class IoStatistics { 00330 00331 public: 00332 00333 IoStatistics (); 00334 00335 IoStatistics operator- (const IoStatistics &) const; 00336 IoStatistics operator+ (const IoStatistics &) const; 00337 IoStatistics operator/ (const IoStatistics &) const; 00338 IoStatistics operator* (Double factor) const; 00339 00340 void capture (); 00341 00342 Double getBytesRead () const; 00343 Double getBytesWritten () const; 00344 Double getNReads () const; 00345 Double getNWrites () const; 00346 00347 String report (float scale = .001, const String & scaleTag = String ("K")) const; 00348 00349 private: 00350 00351 Double nBytesRead_p; 00352 Double nBytesWritten_p; 00353 Double nReads_p; 00354 Double nWrites_p; 00355 String statFile_p; 00356 }; 00357 00358 00359 // These two classes, Times and DeltaTimes should be moved out of this file and 00360 // into casacore/casa/OS. In the meantime, an ifdef should keep the apple from 00361 // barfing. 00362 00363 // <summary> 00364 00365 // </summary> 00366 00367 // <use visibility=local> or <use visibility=export> 00368 00369 // <reviewed reviewer="" date="yyyy/mm/dd" tests="" demos=""> 00370 // </reviewed> 00371 00372 // <prerequisite> 00373 // <li> SomeClass 00374 // <li> SomeOtherClass 00375 // <li> some concept 00376 // </prerequisite> 00377 // 00378 // <etymology> 00379 // </etymology> 00380 // 00381 // <synopsis> 00382 // </synopsis> 00383 // 00384 // <example> 00385 // </example> 00386 // 00387 // <motivation> 00388 // </motivation> 00389 // 00390 // <templating arg=T> 00391 // <li> 00392 // <li> 00393 // </templating> 00394 // 00395 // <thrown> 00396 // <li> 00397 // <li> 00398 // </thrown> 00399 // 00400 // <todo asof="yyyy/mm/dd"> 00401 // <li> add this feature 00402 // <li> fix this bug 00403 // <li> start discussion of this possible extension 00404 // </todo> 00405 00406 class DeltaThreadTimes; 00407 00408 class ThreadTimes { 00409 00410 public: 00411 00412 ThreadTimes () { * this = getTime();} 00413 00414 Double cpu () const { return cpu_p;} 00415 void clear () { empty_p = True;} 00416 Bool empty () const { return empty_p;} 00417 Double elapsed () const { return elapsed_p;} 00418 00419 static ThreadTimes 00420 getTime (){ 00421 00422 struct timeval tVal; 00423 gettimeofday (& tVal, NULL); 00424 00425 Double elapsed = tVal.tv_sec + tVal.tv_usec * 1e-6; 00426 00427 //Double cpu = ((Double) clock ()) / CLOCKS_PER_SEC; // should be in seconds 00428 00429 00430 00431 #if defined (RUSAGE_THREAD) 00432 struct rusage usage; 00433 00434 int failed = getrusage (RUSAGE_THREAD, & usage); 00435 assert (! failed); 00436 00437 Double cpu = ! failed ? toSeconds (usage.ru_utime) + toSeconds (usage.ru_stime) : 0; 00438 #else 00439 Double cpu = 0; 00440 #endif 00441 00442 return ThreadTimes (elapsed, cpu); 00443 } 00444 00445 DeltaThreadTimes operator- (const ThreadTimes & tEarlier) const; 00446 00447 static Double 00448 toSeconds (const struct timeval & t) 00449 { 00450 return t.tv_sec + t.tv_usec * 1e-6; 00451 } 00452 00453 protected: 00454 00455 Bool empty_p; 00456 Double cpu_p; 00457 Double elapsed_p; 00458 00459 ThreadTimes (Double elapsed, Double cpu) : cpu_p (cpu), elapsed_p (elapsed) {} 00460 }; 00461 00462 // <summary> 00463 // </summary> 00464 00465 // <use visibility=local> or <use visibility=export> 00466 00467 // <reviewed reviewer="" date="yyyy/mm/dd" tests="" demos=""> 00468 // </reviewed> 00469 00470 // <prerequisite> 00471 // <li> SomeClass 00472 // <li> SomeOtherClass 00473 // <li> some concept 00474 // </prerequisite> 00475 // 00476 // <etymology> 00477 // </etymology> 00478 // 00479 // <synopsis> 00480 // </synopsis> 00481 // 00482 // <example> 00483 // </example> 00484 // 00485 // <motivation> 00486 // </motivation> 00487 // 00488 // <templating arg=T> 00489 // <li> 00490 // <li> 00491 // </templating> 00492 // 00493 // <thrown> 00494 // <li> 00495 // <li> 00496 // </thrown> 00497 // 00498 // <todo asof="yyyy/mm/dd"> 00499 // <li> add this feature 00500 // <li> fix this bug 00501 // <li> start discussion of this possible extension 00502 // </todo> 00503 class DeltaThreadTimes : private ThreadTimes { 00504 00505 friend class ThreadTimes; 00506 00507 public: 00508 00509 DeltaThreadTimes () : ThreadTimes (0, 0), doStats_p (False), n_p (0) {} 00510 explicit DeltaThreadTimes (bool doStats) : ThreadTimes (0,0), doStats_p (doStats), n_p (0) 00511 { 00512 cpuSsq_p = 0; 00513 cpuMin_p = 1e20; 00514 cpuMax_p = -1e20; 00515 elapsedSsq_p = 0; 00516 elapsedMin_p = 1e20; 00517 elapsedMax_p = -1e20; 00518 } 00519 00520 DeltaThreadTimes & operator += (const DeltaThreadTimes & other); 00521 00522 Double cpu () const { return ThreadTimes::cpu();} 00523 Double cpuAvg () const { return n_p == 0 ? 0 : cpu() / n_p;} 00524 Double elapsed () const { return ThreadTimes::elapsed();} 00525 Double elapsedAvg () const { return n_p == 0 ? 0 : elapsed() / n_p;} 00526 String formatAverage (const String & floatFormat = "%6.1f", 00527 Double scale=1000.0, 00528 const String & units = "ms") const; // to convert to ms 00529 String formatStats (const String & floatFormat = "%6.1f", 00530 Double scale=1000.0, 00531 const String & units = "ms") const; // to convert to ms 00532 Int n() const { return n_p;} 00533 00534 protected: 00535 00536 DeltaThreadTimes (Double elapsed, Double cpu) : ThreadTimes (elapsed, cpu), n_p (0) {} 00537 00538 private: 00539 00540 Double cpuMin_p; 00541 Double cpuMax_p; 00542 Double cpuSsq_p; 00543 Bool doStats_p; 00544 Double elapsedMin_p; 00545 Double elapsedMax_p; 00546 Double elapsedSsq_p; 00547 Int n_p; 00548 }; 00549 00550 // Global Functions 00551 00552 // <linkfrom anchor=unique-string-within-this-file classes="class-1,...,class-n"> 00553 // <here> Global functions </here> for foo and bar. 00554 // </linkfrom> 00555 00556 // A free function is provided that is useful for 00557 // go here... 00558 00559 // <group name=accumulation> 00560 00561 00562 // </group> 00563 00564 /* 00565 00566 Example of using composer and unary. The composed functors have to be derived from std::unary_function 00567 00568 int f(int x) { return x*x;} 00569 int g(int x) { return 2 * x;} 00570 int h(int x) { return 100 + x;} 00571 00572 vector<int> a; 00573 a.push_back(1); 00574 a.push_back(2); 00575 a.push_back(3); 00576 00577 transform (a.begin(), a.end(), std::ostream_iterator<int> (cout, "\n"), compose (unary(f), unary(f))); 00578 00579 // prints out 00580 // 4 00581 // 16 00582 // 36 00583 00584 transform (a.begin(), a.end(), std::ostream_iterator<int> (cout, "\n"), 00585 compose (unary(h), compose (unary(f), unary(f)))); 00586 00587 // prints out 00588 // 104 00589 // 116 00590 // 136 00591 00592 */ 00593 00594 template <typename F, typename G> 00595 class ComposedFunctor : public std::unary_function <typename G::argument_type, typename F::result_type> { 00596 00597 public: 00598 00599 ComposedFunctor (F f, G g) : f_p (f), g_p (g) {} 00600 00601 typename F::result_type operator() (typename G::argument_type x) { return f_p ( g_p (x)); } 00602 00603 private: 00604 00605 F f_p; 00606 G g_p; 00607 }; 00608 00609 template <typename F, typename G> 00610 ComposedFunctor<F, G> 00611 compose (F f, G g) 00612 { 00613 return ComposedFunctor <F, G> (f, g); 00614 } 00615 00616 template <typename D, typename R> 00617 class UnaryFunctor : public std::unary_function<D,R> { 00618 public: 00619 typedef R (* F) (D); 00620 00621 UnaryFunctor (F f) : f_p (f) {} 00622 R operator() (D x) { return f_p (x); } 00623 00624 private: 00625 00626 F f_p; 00627 }; 00628 00629 template <typename D, typename R> 00630 UnaryFunctor <D, R> 00631 unary (R (*f) (D)) { return UnaryFunctor<D, R> (f);} 00632 00633 class Z { 00634 public: 00635 00636 string getName () const { return name_p;} 00637 00638 string name_p; 00639 }; 00640 00641 00642 00643 } // end namespace utilj 00644 00645 } // end namespace casa 00646 00647 00648 #endif /* UTILJ_H_ */