casa  $Rev:20696$
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines
UtilJ.h
Go to the documentation of this file.
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_ */