1 | // =========================================================== // |
---|
2 | // // |
---|
3 | // File : arb_sleep.h // |
---|
4 | // Purpose : // |
---|
5 | // // |
---|
6 | // Coded by Ralf Westram (coder@reallysoft.de) in May 2013 // |
---|
7 | // Institute of Microbiology (Technical University Munich) // |
---|
8 | // http://www.arb-home.de/ // |
---|
9 | // // |
---|
10 | // =========================================================== // |
---|
11 | |
---|
12 | #ifndef ARB_SLEEP_H |
---|
13 | #define ARB_SLEEP_H |
---|
14 | |
---|
15 | #ifndef _UNISTD_H |
---|
16 | #include <unistd.h> |
---|
17 | #endif |
---|
18 | #ifndef _GLIBCXX_ALGORITHM |
---|
19 | #include <algorithm> |
---|
20 | #endif |
---|
21 | #ifndef _TIME_H |
---|
22 | #include <time.h> |
---|
23 | #endif |
---|
24 | #ifndef _SYS_TIME_H |
---|
25 | #include <sys/time.h> |
---|
26 | #endif |
---|
27 | |
---|
28 | // #define TRACE_SLEEP |
---|
29 | |
---|
30 | enum TimeUnit { USEC = 1, MS = 1000, SEC = 1000*MS }; |
---|
31 | |
---|
32 | inline void ARB_sleep(int amount, TimeUnit tu) { |
---|
33 | arb_assert(amount>=0); |
---|
34 | arb_assert(amount<1000*1000); // use different TimeUnit |
---|
35 | |
---|
36 | struct timespec t; |
---|
37 | switch (tu) { |
---|
38 | case USEC: |
---|
39 | t.tv_sec = 0; |
---|
40 | t.tv_nsec = amount*1000; |
---|
41 | break; |
---|
42 | case MS: |
---|
43 | t.tv_sec = amount/MS; |
---|
44 | t.tv_nsec = (amount-t.tv_sec*MS)*MS*1000; |
---|
45 | break; |
---|
46 | case SEC: |
---|
47 | t.tv_sec = amount; |
---|
48 | t.tv_nsec = 0; |
---|
49 | break; |
---|
50 | } |
---|
51 | |
---|
52 | arb_assert(t.tv_sec>=0); |
---|
53 | arb_assert(t.tv_nsec>=0 && t.tv_nsec<=999999999); |
---|
54 | |
---|
55 | while (1) { |
---|
56 | struct timespec remain; |
---|
57 | |
---|
58 | int res = nanosleep(&t, &remain); |
---|
59 | if (res == 0) break; |
---|
60 | // nanosleep has been interrupted by signal -> call again |
---|
61 | t = remain; |
---|
62 | } |
---|
63 | } |
---|
64 | |
---|
65 | #if defined(TRACE_SLEEP) |
---|
66 | inline const char *timeUnitAbbr(TimeUnit tu) { |
---|
67 | switch (tu) { |
---|
68 | case USEC: return "usec"; |
---|
69 | case MS: return "ms"; |
---|
70 | case SEC: return "s"; |
---|
71 | } |
---|
72 | arb_assert(0); |
---|
73 | return ""; |
---|
74 | } |
---|
75 | #endif |
---|
76 | |
---|
77 | class ARB_inc_sleep { |
---|
78 | int curr_wait, max_wait, inc; |
---|
79 | TimeUnit unit; |
---|
80 | |
---|
81 | void slowdown() { curr_wait = std::min(max_wait, curr_wait+inc); } |
---|
82 | public: |
---|
83 | ARB_inc_sleep(int min_amount, int max_amount, TimeUnit tu, int increment) |
---|
84 | : curr_wait(min_amount), |
---|
85 | max_wait(max_amount), |
---|
86 | inc(increment), |
---|
87 | unit(tu) |
---|
88 | { |
---|
89 | arb_assert(curr_wait>0); |
---|
90 | arb_assert(max_amount>=curr_wait); |
---|
91 | arb_assert(increment>0); |
---|
92 | } |
---|
93 | |
---|
94 | void sleep() { |
---|
95 | #if defined(TRACE_SLEEP) |
---|
96 | fprintf(stderr, "pid %i waits %i %s\n", getpid(), curr_wait, timeUnitAbbr(unit)); |
---|
97 | #endif |
---|
98 | ARB_sleep(curr_wait, unit); |
---|
99 | slowdown(); |
---|
100 | } |
---|
101 | }; |
---|
102 | |
---|
103 | class ARB_timestamp { |
---|
104 | // timer which can be asked how much time passed since it was initialized |
---|
105 | timeval t1; |
---|
106 | |
---|
107 | public: |
---|
108 | ARB_timestamp() { update(); } |
---|
109 | void update() { gettimeofday(&t1, NULp); } |
---|
110 | |
---|
111 | long usec_since() const { |
---|
112 | timeval t2; |
---|
113 | gettimeofday(&t2, NULp); |
---|
114 | return (t2.tv_sec - t1.tv_sec) * SEC + (t2.tv_usec - t1.tv_usec); |
---|
115 | } |
---|
116 | long ms_since() const { return usec_since()/MS; } |
---|
117 | long sec_since() const { return usec_since()/SEC; } |
---|
118 | }; |
---|
119 | |
---|
120 | class ARB_timeout { |
---|
121 | // short timeout |
---|
122 | ARB_timestamp start; |
---|
123 | long amount_usec; |
---|
124 | public: |
---|
125 | ARB_timeout(int amount, TimeUnit tu) |
---|
126 | : amount_usec(amount*tu) |
---|
127 | {} |
---|
128 | bool passed() const { |
---|
129 | return start.usec_since()>=amount_usec; |
---|
130 | } |
---|
131 | }; |
---|
132 | |
---|
133 | |
---|
134 | #else |
---|
135 | #error arb_sleep.h included twice |
---|
136 | #endif // ARB_SLEEP_H |
---|