Line data Source code
1 : /*
2 : * UtilJ.h
3 : *
4 : * Created on: Nov 4, 2010
5 : * Author: jjacobs
6 : */
7 :
8 : #ifndef UTILJ_H_
9 : #define UTILJ_H_
10 :
11 : // Casa Includes
12 :
13 : #include <casacore/casa/aips.h>
14 : #include <casacore/casa/BasicSL/String.h>
15 : #include <casacore/casa/Exceptions/Error.h>
16 :
17 : // C++ and System Includes
18 :
19 : #include <cassert>
20 : #include <cstdarg>
21 : #include <cstdlib>
22 : #include <sys/time.h>
23 : #include <sys/resource.h>
24 : // STL Includes
25 : #include <algorithm>
26 : #include <functional>
27 : #include <iterator>
28 : #include <map>
29 : #include <set>
30 : #include <vector>
31 :
32 : #ifdef __GNUC__
33 : #define DEPRECATED(func) func __attribute__ ((deprecated))
34 : #elif defined(_MSC_VER)
35 : #define DEPRECATED(func) __declspec(deprecated) func
36 : #else
37 : ///#pragma message("WARNING: You need to implement DEPRECATED for this compiler")
38 : #define DEPRECATED(func) func
39 : #endif
40 :
41 : #ifdef __GNUC__
42 : #define DEPRECATED_METHOD(comment) __attribute__ ((deprecated))
43 : #else
44 : ///#pragma message("WARNING: You need to implement DEPRECATED for this compiler")
45 : #define DEPRECATED_METHOD(comment)
46 : #endif
47 :
48 : #define Assert AssertCc
49 : #define Throw ThrowCc
50 :
51 : #define UnusedVariable(x) ((void) x);
52 :
53 : namespace casacore{
54 :
55 : class String;
56 : }
57 :
58 : namespace casa {
59 :
60 : namespace utilj {
61 :
62 : class AipsErrorTrace : public casacore::AipsError {
63 :
64 : public:
65 :
66 : AipsErrorTrace ( const casacore::String &msg, const casacore::String &filename, casacore::uInt lineNumber,
67 : Category c = GENERAL);
68 :
69 : };
70 :
71 : class Strings : public std::vector<casacore::String> {};
72 :
73 : //template <typename Element, typename Container>
74 : //bool
75 : //contains (const Element & e, const Container & c)
76 : //{
77 : // return c.find(e) != c.end();
78 : //}
79 :
80 :
81 : template <typename Container>
82 : bool
83 65752 : containsKey (const typename Container::key_type & key,
84 : const Container & container)
85 : {
86 65752 : return container.find(key) != container.end();
87 : }
88 :
89 : template <typename Container>
90 : bool
91 0 : contains (const typename Container::value_type & e,
92 : const Container & c)
93 : {
94 : // For set and map use containsKey; will work for set but
95 : // use with map requires specifying a pair as the first argument
96 :
97 0 : return std::find(c.begin(), c.end(), e) != c.end();
98 : }
99 :
100 : template <typename F, typename S>
101 : F & first (std::pair<F,S> & pair) { return pair.first;}
102 :
103 : template <typename F, typename S>
104 : const F & first (const std::pair<F,S> & pair) { return pair.first;}
105 :
106 : template <typename F, typename S>
107 : class FirstFunctor{
108 : public:
109 : typedef std::pair<F,S> argument_type;
110 : typedef F result_type;
111 0 : F & operator() (std::pair<F,S> & p) { return p.first; }
112 0 : const F & operator() (const std::pair<F,S> & p) { return p.first; }
113 : };
114 :
115 : template <typename Container, typename Element>
116 : Container
117 : fillContainer (Element sentinel, ...)
118 : {
119 : using namespace std;
120 :
121 : Container container;
122 :
123 : va_list vaList;
124 : va_start (vaList, sentinel);
125 :
126 : Element e = va_arg (vaList, Element);
127 :
128 : insert_iterator<Container> i = inserter (container, container.begin());
129 :
130 : while (e != sentinel){
131 :
132 : * i ++ = e;
133 :
134 : e = va_arg (vaList, Element);
135 : }
136 :
137 : va_end (vaList);
138 :
139 : return container;
140 : }
141 :
142 : template <typename F, typename S>
143 0 : FirstFunctor<F,S> firstFunctor () { return FirstFunctor<F,S> ();}
144 :
145 :
146 : //DEPRECATED (casacore::String format (const char * formatString, ...) /* "Use casacore::String::format"*/);
147 : casacore::String formatV (const casacore::String & formatString, va_list vaList);
148 :
149 : template<typename T>
150 : T
151 : getEnv (const casacore::String & name, const T & defaultValue)
152 : {
153 : char * value = getenv (name.c_str());
154 :
155 : if (value == NULL){
156 : return defaultValue;
157 : }
158 : else{
159 : return T (value);
160 : }
161 : }
162 :
163 : bool
164 : getEnv (const casacore::String & name, const bool & defaultValue);
165 :
166 : int
167 : getEnv (const casacore::String & name, const int & defaultValue);
168 :
169 :
170 : casacore::String getTimestamp ();
171 :
172 : bool isEnvDefined (const casacore::String & name);
173 :
174 : std::vector<casacore::String> split (const casacore::String & string, const casacore::String & splitter,
175 : bool ignoreConsecutiveSplitters = false);
176 :
177 : template <typename Itr>
178 : casacore::String
179 0 : join (Itr begin, Itr end, const casacore::String & delimiter)
180 : {
181 0 : casacore::String result;
182 0 : Itr i = begin;
183 :
184 0 : if (i != end){
185 :
186 0 : result = * i ++;
187 :
188 0 : for (; i != end; i++){
189 0 : result += delimiter + * i;
190 : }
191 : }
192 :
193 0 : return result;
194 0 : }
195 :
196 : template <typename T>
197 : casacore::String
198 0 : join (const T & strings, const casacore::String & delimiter)
199 : {
200 0 : return join (strings.begin(), strings.end(), delimiter);
201 : }
202 :
203 : template <typename Itr, typename F>
204 : casacore::String
205 0 : join (Itr begin, Itr end, F f, const casacore::String & delimiter)
206 : {
207 0 : casacore::String result;
208 0 : Itr i = begin;
209 :
210 0 : if (i != end){
211 :
212 0 : result = f(* i);
213 0 : ++ i;
214 :
215 0 : for (; i != end; i++){
216 0 : result += delimiter + f (* i);
217 : }
218 : }
219 :
220 0 : return result;
221 0 : }
222 :
223 : template <typename K, typename V>
224 : std::vector<K>
225 0 : mapKeys (const std::map<K,V> & aMap)
226 : {
227 0 : std::vector<K> result;
228 :
229 0 : std::transform (aMap.begin(), aMap.end(), back_inserter (result), firstFunctor<K,V>());
230 :
231 0 : return result;
232 0 : }
233 :
234 : casacore::AipsError repackageAipsError (casacore::AipsError & error,
235 : const casacore::String & message,
236 : const casacore::String & file,
237 : int line, const casacore::String & func);
238 :
239 : template <typename F, typename S>
240 : F & second (std::pair<F,S> & pair) { return pair.second;}
241 :
242 : template <typename F, typename S>
243 : const F & second (const std::pair<F,S> & pair) { return pair.second;}
244 :
245 : template <typename F, typename S>
246 : class SecondFunctor{
247 : public:
248 : typedef std::pair<F,S> argument_type;
249 : typedef F result_type;
250 : S & operator() (std::pair<F,S> & p) { return p.second; }
251 : };
252 :
253 : template <typename F, typename S>
254 : SecondFunctor<F,S> secondFunctor () { return SecondFunctor<F,S> ();}
255 :
256 : template <typename K, typename V>
257 : std::vector<V>
258 : mapValues (const std::map<K,V> & aMap)
259 : {
260 : std::vector<K> result (aMap.size());
261 :
262 : std::transform (aMap.begin(), aMap.end(), back_inserter (result), second<K,V>);
263 :
264 : return result;
265 : }
266 :
267 : void printBacktrace (std::ostream & os, const casacore::String & prefix = "");
268 :
269 : long round (double d);
270 :
271 : void sleepMs (int milliseconds);
272 : void toStdError (const casacore::String & m, const casacore::String & prefix = "*E* ");
273 : void throwIf (bool condition, const casacore::String & message, const casacore::String & file,
274 : int line, const casacore::String & func = casacore::String());
275 : void throwIfError (int errorCode, const casacore::String & prefix, const casacore::String & file,
276 : int line, const casacore::String & func = casacore::String());
277 :
278 : template <typename It, typename Obj>
279 : casacore::String
280 0 : containerToString (It begin, It end, casacore::String (Obj::* func) () const, const casacore::String & delimiter = ",",
281 : const casacore::String & wrapper = "")
282 : {
283 0 : casacore::String result;
284 0 : casacore::String d = "";
285 :
286 0 : for (It i = begin; i != end; i++){
287 0 : result += d + wrapper + ((* i) .* func) () + wrapper;
288 0 : d = delimiter;
289 : }
290 :
291 0 : return result;
292 0 : }
293 :
294 : class MemoryStatistics {
295 :
296 : public:
297 :
298 : MemoryStatistics ();
299 :
300 : void update (); // call to get the latest stats loaded
301 : double getRssInMB () const; // get resident set size
302 : int64_t getRssInBytes () const;
303 :
304 : double getVmInMB () const; // get the Virtual memory size
305 : int64_t getVmInBytes () const;
306 :
307 : private:
308 :
309 : double bytesPerMb_p;
310 : string filename_p;
311 : int pageSize_p;
312 : int64_t rssPages_p; // in pages
313 : int64_t vmPages_p; // in pages
314 : };
315 :
316 : class IoStatistics {
317 :
318 : public:
319 :
320 : IoStatistics ();
321 :
322 : IoStatistics operator- (const IoStatistics &) const;
323 : IoStatistics operator+ (const IoStatistics &) const;
324 : IoStatistics operator/ (const IoStatistics &) const;
325 : IoStatistics operator* (double factor) const;
326 :
327 : void capture ();
328 :
329 : double getBytesRead () const;
330 : double getBytesWritten () const;
331 : double getNReads () const;
332 : double getNWrites () const;
333 :
334 : casacore::String report (float scale = .001, const casacore::String & scaleTag = casacore::String ("K")) const;
335 :
336 : private:
337 :
338 : double nBytesRead_p;
339 : double nBytesWritten_p;
340 : double nReads_p;
341 : double nWrites_p;
342 : casacore::String statFile_p;
343 : };
344 :
345 :
346 : // These two classes, Times and DeltaTimes should be moved out of this file and
347 : // into casacore/casa/OS. In the meantime, an ifdef should keep the apple from
348 : // barfing.
349 :
350 : // <summary>
351 :
352 : // </summary>
353 :
354 : // <use visibility=local> or <use visibility=export>
355 :
356 : // <reviewed reviewer="" date="yyyy/mm/dd" tests="" demos="">
357 : // </reviewed>
358 :
359 : // <prerequisite>
360 : // <li> SomeClass
361 : // <li> SomeOtherClass
362 : // <li> some concept
363 : // </prerequisite>
364 : //
365 : // <etymology>
366 : // </etymology>
367 : //
368 : // <synopsis>
369 : // </synopsis>
370 : //
371 : // <example>
372 : // </example>
373 : //
374 : // <motivation>
375 : // </motivation>
376 : //
377 : // <templating arg=T>
378 : // <li>
379 : // <li>
380 : // </templating>
381 : //
382 : // <thrown>
383 : // <li>
384 : // <li>
385 : // </thrown>
386 : //
387 : // <todo asof="yyyy/mm/dd">
388 : // <li> add this feature
389 : // <li> fix this bug
390 : // <li> start discussion of this possible extension
391 : // </todo>
392 :
393 : class DeltaThreadTimes;
394 :
395 : class ThreadTimes {
396 :
397 : public:
398 :
399 0 : ThreadTimes () { * this = getTime();}
400 :
401 0 : double cpu () const { return cpu_p;}
402 : void clear () { empty_p = true;}
403 : bool empty () const { return empty_p;}
404 0 : double elapsed () const { return elapsed_p;}
405 :
406 : static ThreadTimes
407 0 : getTime (){
408 :
409 : struct timeval tVal;
410 0 : gettimeofday (& tVal, NULL);
411 :
412 0 : double elapsed = tVal.tv_sec + tVal.tv_usec * 1e-6;
413 :
414 : //double cpu = ((double) clock ()) / CLOCKS_PER_SEC; // should be in seconds
415 :
416 :
417 :
418 : #if defined (RUSAGE_THREAD)
419 : struct rusage usage;
420 :
421 0 : int failed = getrusage (RUSAGE_THREAD, & usage);
422 0 : assert (! failed);
423 :
424 0 : double cpu = ! failed ? toSeconds (usage.ru_utime) + toSeconds (usage.ru_stime) : 0;
425 : #else
426 : double cpu = 0;
427 : #endif
428 :
429 0 : return ThreadTimes (elapsed, cpu);
430 : }
431 :
432 : DeltaThreadTimes operator- (const ThreadTimes & tEarlier) const;
433 :
434 : static double
435 0 : toSeconds (const struct timeval & t)
436 : {
437 0 : return t.tv_sec + t.tv_usec * 1e-6;
438 : }
439 :
440 : protected:
441 :
442 : bool empty_p;
443 : double cpu_p;
444 : double elapsed_p;
445 :
446 0 : ThreadTimes (double elapsed, double cpu) : cpu_p (cpu), elapsed_p (elapsed) {}
447 : };
448 :
449 : // <summary>
450 : // </summary>
451 :
452 : // <use visibility=local> or <use visibility=export>
453 :
454 : // <reviewed reviewer="" date="yyyy/mm/dd" tests="" demos="">
455 : // </reviewed>
456 :
457 : // <prerequisite>
458 : // <li> SomeClass
459 : // <li> SomeOtherClass
460 : // <li> some concept
461 : // </prerequisite>
462 : //
463 : // <etymology>
464 : // </etymology>
465 : //
466 : // <synopsis>
467 : // </synopsis>
468 : //
469 : // <example>
470 : // </example>
471 : //
472 : // <motivation>
473 : // </motivation>
474 : //
475 : // <templating arg=T>
476 : // <li>
477 : // <li>
478 : // </templating>
479 : //
480 : // <thrown>
481 : // <li>
482 : // <li>
483 : // </thrown>
484 : //
485 : // <todo asof="yyyy/mm/dd">
486 : // <li> add this feature
487 : // <li> fix this bug
488 : // <li> start discussion of this possible extension
489 : // </todo>
490 : class DeltaThreadTimes : private ThreadTimes {
491 :
492 : friend class ThreadTimes;
493 :
494 : public:
495 :
496 0 : DeltaThreadTimes () : ThreadTimes (0, 0), doStats_p (false), n_p (0) {}
497 0 : explicit DeltaThreadTimes (bool doStats) : ThreadTimes (0,0), doStats_p (doStats), n_p (0)
498 : {
499 0 : cpuSsq_p = 0;
500 0 : cpuMin_p = 1e20;
501 0 : cpuMax_p = -1e20;
502 0 : elapsedSsq_p = 0;
503 0 : elapsedMin_p = 1e20;
504 0 : elapsedMax_p = -1e20;
505 0 : }
506 :
507 : DeltaThreadTimes & operator += (const DeltaThreadTimes & other);
508 :
509 0 : double cpu () const { return ThreadTimes::cpu();}
510 : double cpuAvg () const { return n_p == 0 ? 0 : cpu() / n_p;}
511 0 : double elapsed () const { return ThreadTimes::elapsed();}
512 0 : double elapsedAvg () const { return n_p == 0 ? 0 : elapsed() / n_p;}
513 : casacore::String formatAverage (const casacore::String & floatFormat = "%6.1f",
514 : double scale=1000.0,
515 : const casacore::String & units = "ms") const; // to convert to ms
516 : casacore::String formatStats (const casacore::String & floatFormat = "%6.1f",
517 : double scale=1000.0,
518 : const casacore::String & units = "ms") const; // to convert to ms
519 0 : int n() const { return n_p;}
520 :
521 : protected:
522 :
523 0 : DeltaThreadTimes (double elapsed, double cpu) : ThreadTimes (elapsed, cpu), n_p (0) {}
524 :
525 : private:
526 :
527 : double cpuMin_p;
528 : double cpuMax_p;
529 : double cpuSsq_p;
530 : bool doStats_p;
531 : double elapsedMin_p;
532 : double elapsedMax_p;
533 : double elapsedSsq_p;
534 : int n_p;
535 : };
536 :
537 : // Global Functions
538 :
539 : // <linkfrom anchor=unique-string-within-this-file classes="class-1,...,class-n">
540 : // <here> Global functions </here> for foo and bar.
541 : // </linkfrom>
542 :
543 : // A free function is provided that is useful for
544 : // go here...
545 :
546 : // <group name=accumulation>
547 :
548 :
549 : // </group>
550 :
551 : /*
552 :
553 : Example of using composer and unary. The composed functors have to be derived from std::unary_function
554 :
555 : int f(int x) { return x*x;}
556 : int g(int x) { return 2 * x;}
557 : int h(int x) { return 100 + x;}
558 :
559 : vector<int> a;
560 : a.push_back(1);
561 : a.push_back(2);
562 : a.push_back(3);
563 :
564 : transform (a.begin(), a.end(), std::ostream_iterator<int> (cout, "\n"), compose (unary(f), unary(f)));
565 :
566 : // prints out
567 : // 4
568 : // 16
569 : // 36
570 :
571 : transform (a.begin(), a.end(), std::ostream_iterator<int> (cout, "\n"),
572 : compose (unary(h), compose (unary(f), unary(f))));
573 :
574 : // prints out
575 : // 104
576 : // 116
577 : // 136
578 :
579 : */
580 :
581 : template <typename F, typename G>
582 : class ComposedFunctor {
583 :
584 : public:
585 :
586 : typedef typename G::argument_type argument_type;
587 : typedef typename F::result_type result_type;
588 0 : ComposedFunctor (F f, G g) : f_p (f), g_p (g) {}
589 :
590 0 : typename F::result_type operator() (typename G::argument_type x) { return f_p ( g_p (x)); }
591 :
592 : private:
593 :
594 : F f_p;
595 : G g_p;
596 : };
597 :
598 : template <typename F, typename G>
599 : ComposedFunctor<F, G>
600 0 : compose (F f, G g)
601 : {
602 0 : return ComposedFunctor <F, G> (f, g);
603 : }
604 :
605 : template <typename D, typename R>
606 : class UnaryFunctor{
607 : public:
608 :
609 : typedef D argument_type;
610 : typedef R result_type;
611 : typedef R (* F) (D);
612 :
613 : UnaryFunctor (F f) : f_p (f) {}
614 : R operator() (D x) { return f_p (x); }
615 :
616 : private:
617 :
618 : F f_p;
619 : };
620 :
621 : template <typename D, typename R>
622 : UnaryFunctor <D, R>
623 : unary (R (*f) (D)) { return UnaryFunctor<D, R> (f);}
624 :
625 : class Z {
626 : public:
627 :
628 : string getName () const { return name_p;}
629 :
630 : string name_p;
631 : };
632 :
633 :
634 :
635 : } // end namespace utilj
636 :
637 : } // end namespace casa
638 :
639 :
640 :
641 : #endif /* UTILJ_H_ */
|