/* * UtilJ.h * * Created on: Nov 4, 2010 * Author: jjacobs */ #ifndef UTILJ_H_ #define UTILJ_H_ // Casa Includes #include <casacore/casa/aips.h> #include <casacore/casa/BasicSL/String.h> #include <casacore/casa/Exceptions/Error.h> // C++ and System Includes #include <cassert> #include <cstdarg> #include <cstdlib> #include <sys/time.h> #include <sys/resource.h> // STL Includes #include <algorithm> #include <functional> #include <iterator> #include <map> #include <set> #include <vector> #ifdef __GNUC__ #define DEPRECATED(func) func __attribute__ ((deprecated)) #elif defined(_MSC_VER) #define DEPRECATED(func) __declspec(deprecated) func #else ///#pragma message("WARNING: You need to implement DEPRECATED for this compiler") #define DEPRECATED(func) func #endif #ifdef __GNUC__ #define DEPRECATED_METHOD(comment) __attribute__ ((deprecated)) #else ///#pragma message("WARNING: You need to implement DEPRECATED for this compiler") #define DEPRECATED_METHOD(comment) #endif #define Assert AssertCc #define Throw ThrowCc #define UnusedVariable(x) ((void) x); namespace casacore{ class String; } namespace casa { namespace utilj { class AipsErrorTrace : public casacore::AipsError { public: AipsErrorTrace ( const casacore::String &msg, const casacore::String &filename, casacore::uInt lineNumber, Category c = GENERAL); }; class Strings : public std::vector<casacore::String> {}; //template <typename Element, typename Container> //bool //contains (const Element & e, const Container & c) //{ // return c.find(e) != c.end(); //} template <typename Container> bool containsKey (const typename Container::key_type & key, const Container & container) { return container.find(key) != container.end(); } template <typename Container> bool contains (const typename Container::value_type & e, const Container & c) { // For set and map use containsKey; will work for set but // use with map requires specifying a pair as the first argument return std::find(c.begin(), c.end(), e) != c.end(); } template <typename F, typename S> F & first (std::pair<F,S> & pair) { return pair.first;} template <typename F, typename S> const F & first (const std::pair<F,S> & pair) { return pair.first;} template <typename F, typename S> class FirstFunctor : public std::unary_function<std::pair<F,S>, F>{ public: F & operator() (std::pair<F,S> & p) { return p.first; } const F & operator() (const std::pair<F,S> & p) { return p.first; } }; template <typename Container, typename Element> Container fillContainer (Element sentinel, ...) { using namespace std; Container container; va_list vaList; va_start (vaList, sentinel); Element e = va_arg (vaList, Element); insert_iterator<Container> i = inserter (container, container.begin()); while (e != sentinel){ * i ++ = e; e = va_arg (vaList, Element); } va_end (vaList); return container; } template <typename F, typename S> FirstFunctor<F,S> firstFunctor () { return FirstFunctor<F,S> ();} //DEPRECATED (casacore::String format (const char * formatString, ...) /* "Use casacore::String::format"*/); casacore::String formatV (const casacore::String & formatString, va_list vaList); template<typename T> T getEnv (const casacore::String & name, const T & defaultValue) { char * value = getenv (name.c_str()); if (value == NULL){ return defaultValue; } else{ return T (value); } } bool getEnv (const casacore::String & name, const bool & defaultValue); int getEnv (const casacore::String & name, const int & defaultValue); casacore::String getTimestamp (); bool isEnvDefined (const casacore::String & name); std::vector<casacore::String> split (const casacore::String & string, const casacore::String & splitter, bool ignoreConsecutiveSplitters = false); template <typename Itr> casacore::String join (Itr begin, Itr end, const casacore::String & delimiter) { casacore::String result; Itr i = begin; if (i != end){ result = * i ++; for (; i != end; i++){ result += delimiter + * i; } } return result; } template <typename T> casacore::String join (const T & strings, const casacore::String & delimiter) { return join (strings.begin(), strings.end(), delimiter); } template <typename Itr, typename F> casacore::String join (Itr begin, Itr end, F f, const casacore::String & delimiter) { casacore::String result; Itr i = begin; if (i != end){ result = f(* i); ++ i; for (; i != end; i++){ result += delimiter + f (* i); } } return result; } template <typename K, typename V> std::vector<K> mapKeys (const std::map<K,V> & aMap) { std::vector<K> result; std::transform (aMap.begin(), aMap.end(), back_inserter (result), firstFunctor<K,V>()); return result; } casacore::AipsError repackageAipsError (casacore::AipsError & error, const casacore::String & message, const casacore::String & file, int line, const casacore::String & func); template <typename F, typename S> F & second (std::pair<F,S> & pair) { return pair.second;} template <typename F, typename S> const F & second (const std::pair<F,S> & pair) { return pair.second;} template <typename F, typename S> class SecondFunctor : public std::unary_function<std::pair<F,S>, F>{ public: S & operator() (std::pair<F,S> & p) { return p.second; } }; template <typename F, typename S> SecondFunctor<F,S> secondFunctor () { return SecondFunctor<F,S> ();} template <typename K, typename V> std::vector<V> mapValues (const std::map<K,V> & aMap) { std::vector<K> result (aMap.size()); std::transform (aMap.begin(), aMap.end(), back_inserter (result), second<K,V>); return result; } void printBacktrace (std::ostream & os, const casacore::String & prefix = ""); long round (double d); void sleepMs (int milliseconds); void toStdError (const casacore::String & m, const casacore::String & prefix = "*E* "); void throwIf (bool condition, const casacore::String & message, const casacore::String & file, int line, const casacore::String & func = casacore::String()); void throwIfError (int errorCode, const casacore::String & prefix, const casacore::String & file, int line, const casacore::String & func = casacore::String()); template <typename It, typename Obj> casacore::String containerToString (It begin, It end, casacore::String (Obj::* func) () const, const casacore::String & delimiter = ",", const casacore::String & wrapper = "") { casacore::String result; casacore::String d = ""; for (It i = begin; i != end; i++){ result += d + wrapper + ((* i) .* func) () + wrapper; d = delimiter; } return result; } class MemoryStatistics { public: MemoryStatistics (); void update (); // call to get the latest stats loaded double getRssInMB () const; // get resident set size int64_t getRssInBytes () const; double getVmInMB () const; // get the Virtual memory size int64_t getVmInBytes () const; private: double bytesPerMb_p; string filename_p; int pageSize_p; int64_t rssPages_p; // in pages int64_t vmPages_p; // in pages }; class IoStatistics { public: IoStatistics (); IoStatistics operator- (const IoStatistics &) const; IoStatistics operator+ (const IoStatistics &) const; IoStatistics operator/ (const IoStatistics &) const; IoStatistics operator* (double factor) const; void capture (); double getBytesRead () const; double getBytesWritten () const; double getNReads () const; double getNWrites () const; casacore::String report (float scale = .001, const casacore::String & scaleTag = casacore::String ("K")) const; private: double nBytesRead_p; double nBytesWritten_p; double nReads_p; double nWrites_p; casacore::String statFile_p; }; // These two classes, Times and DeltaTimes should be moved out of this file and // into casacore/casa/OS. In the meantime, an ifdef should keep the apple from // barfing. // <summary> // </summary> // <use visibility=local> or <use visibility=export> // <reviewed reviewer="" date="yyyy/mm/dd" tests="" demos=""> // </reviewed> // <prerequisite> // <li> SomeClass // <li> SomeOtherClass // <li> some concept // </prerequisite> // // <etymology> // </etymology> // // <synopsis> // </synopsis> // // <example> // </example> // // <motivation> // </motivation> // // <templating arg=T> // <li> // <li> // </templating> // // <thrown> // <li> // <li> // </thrown> // // <todo asof="yyyy/mm/dd"> // <li> add this feature // <li> fix this bug // <li> start discussion of this possible extension // </todo> class DeltaThreadTimes; class ThreadTimes { public: ThreadTimes () { * this = getTime();} double cpu () const { return cpu_p;} void clear () { empty_p = true;} bool empty () const { return empty_p;} double elapsed () const { return elapsed_p;} static ThreadTimes getTime (){ struct timeval tVal; gettimeofday (& tVal, NULL); double elapsed = tVal.tv_sec + tVal.tv_usec * 1e-6; //double cpu = ((double) clock ()) / CLOCKS_PER_SEC; // should be in seconds #if defined (RUSAGE_THREAD) struct rusage usage; int failed = getrusage (RUSAGE_THREAD, & usage); assert (! failed); double cpu = ! failed ? toSeconds (usage.ru_utime) + toSeconds (usage.ru_stime) : 0; #else double cpu = 0; #endif return ThreadTimes (elapsed, cpu); } DeltaThreadTimes operator- (const ThreadTimes & tEarlier) const; static double toSeconds (const struct timeval & t) { return t.tv_sec + t.tv_usec * 1e-6; } protected: bool empty_p; double cpu_p; double elapsed_p; ThreadTimes (double elapsed, double cpu) : cpu_p (cpu), elapsed_p (elapsed) {} }; // <summary> // </summary> // <use visibility=local> or <use visibility=export> // <reviewed reviewer="" date="yyyy/mm/dd" tests="" demos=""> // </reviewed> // <prerequisite> // <li> SomeClass // <li> SomeOtherClass // <li> some concept // </prerequisite> // // <etymology> // </etymology> // // <synopsis> // </synopsis> // // <example> // </example> // // <motivation> // </motivation> // // <templating arg=T> // <li> // <li> // </templating> // // <thrown> // <li> // <li> // </thrown> // // <todo asof="yyyy/mm/dd"> // <li> add this feature // <li> fix this bug // <li> start discussion of this possible extension // </todo> class DeltaThreadTimes : private ThreadTimes { friend class ThreadTimes; public: DeltaThreadTimes () : ThreadTimes (0, 0), doStats_p (false), n_p (0) {} explicit DeltaThreadTimes (bool doStats) : ThreadTimes (0,0), doStats_p (doStats), n_p (0) { cpuSsq_p = 0; cpuMin_p = 1e20; cpuMax_p = -1e20; elapsedSsq_p = 0; elapsedMin_p = 1e20; elapsedMax_p = -1e20; } DeltaThreadTimes & operator += (const DeltaThreadTimes & other); double cpu () const { return ThreadTimes::cpu();} double cpuAvg () const { return n_p == 0 ? 0 : cpu() / n_p;} double elapsed () const { return ThreadTimes::elapsed();} double elapsedAvg () const { return n_p == 0 ? 0 : elapsed() / n_p;} casacore::String formatAverage (const casacore::String & floatFormat = "%6.1f", double scale=1000.0, const casacore::String & units = "ms") const; // to convert to ms casacore::String formatStats (const casacore::String & floatFormat = "%6.1f", double scale=1000.0, const casacore::String & units = "ms") const; // to convert to ms int n() const { return n_p;} protected: DeltaThreadTimes (double elapsed, double cpu) : ThreadTimes (elapsed, cpu), n_p (0) {} private: double cpuMin_p; double cpuMax_p; double cpuSsq_p; bool doStats_p; double elapsedMin_p; double elapsedMax_p; double elapsedSsq_p; int n_p; }; // Global Functions // <linkfrom anchor=unique-string-within-this-file classes="class-1,...,class-n"> // <here> Global functions </here> for foo and bar. // </linkfrom> // A free function is provided that is useful for // go here... // <group name=accumulation> // </group> /* Example of using composer and unary. The composed functors have to be derived from std::unary_function int f(int x) { return x*x;} int g(int x) { return 2 * x;} int h(int x) { return 100 + x;} vector<int> a; a.push_back(1); a.push_back(2); a.push_back(3); transform (a.begin(), a.end(), std::ostream_iterator<int> (cout, "\n"), compose (unary(f), unary(f))); // prints out // 4 // 16 // 36 transform (a.begin(), a.end(), std::ostream_iterator<int> (cout, "\n"), compose (unary(h), compose (unary(f), unary(f)))); // prints out // 104 // 116 // 136 */ template <typename F, typename G> class ComposedFunctor : public std::unary_function <typename G::argument_type, typename F::result_type> { public: ComposedFunctor (F f, G g) : f_p (f), g_p (g) {} typename F::result_type operator() (typename G::argument_type x) { return f_p ( g_p (x)); } private: F f_p; G g_p; }; template <typename F, typename G> ComposedFunctor<F, G> compose (F f, G g) { return ComposedFunctor <F, G> (f, g); } template <typename D, typename R> class UnaryFunctor : public std::unary_function<D,R> { public: typedef R (* F) (D); UnaryFunctor (F f) : f_p (f) {} R operator() (D x) { return f_p (x); } private: F f_p; }; template <typename D, typename R> UnaryFunctor <D, R> unary (R (*f) (D)) { return UnaryFunctor<D, R> (f);} class Z { public: string getName () const { return name_p;} string name_p; }; } // end namespace utilj } // end namespace casa #endif /* UTILJ_H_ */