added some precautionary checks in bdecoder
[libtorrent.git] / include / libtorrent / time.hpp
blobca9e2d85b19c9ca7d10ccbc7c38caafedad5a6f2
1 /*
3 Copyright (c) 2007, Arvid Norberg
4 All rights reserved.
6 Redistribution and use in source and binary forms, with or without
7 modification, are permitted provided that the following conditions
8 are met:
10 * Redistributions of source code must retain the above copyright
11 notice, this list of conditions and the following disclaimer.
12 * Redistributions in binary form must reproduce the above copyright
13 notice, this list of conditions and the following disclaimer in
14 the documentation and/or other materials provided with the distribution.
15 * Neither the name of the author nor the names of its
16 contributors may be used to endorse or promote products derived
17 from this software without specific prior written permission.
19 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
23 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 POSSIBILITY OF SUCH DAMAGE.
33 #ifndef TORRENT_TIME_HPP_INCLUDED
34 #define TORRENT_TIME_HPP_INCLUDED
36 #include <ctime>
37 #include <boost/version.hpp>
39 #ifndef _WIN32
40 #include <unistd.h>
41 #endif
43 namespace libtorrent
45 inline char const* time_now_string()
47 time_t t = std::time(0);
48 tm* timeinfo = std::localtime(&t);
49 static char str[200];
50 std::strftime(str, 200, "%b %d %X", timeinfo);
51 return str;
54 std::string log_time();
57 #if (!defined (__MACH__) && !defined (_WIN32) && (!defined(_POSIX_MONOTONIC_CLOCK) \
58 || _POSIX_MONOTONIC_CLOCK < 0)) || defined (TORRENT_USE_BOOST_DATE_TIME)
60 #include <boost/date_time/posix_time/posix_time_types.hpp>
61 #include "libtorrent/assert.hpp"
63 namespace libtorrent
65 typedef boost::posix_time::ptime ptime;
66 typedef boost::posix_time::time_duration time_duration;
67 inline ptime time_now()
68 { return boost::posix_time::microsec_clock::universal_time(); }
69 inline ptime min_time()
70 { return boost::posix_time::ptime(boost::posix_time::min_date_time); }
71 inline ptime max_time()
72 { return boost::posix_time::ptime(boost::posix_time::max_date_time); }
73 inline time_duration seconds(int s) { return boost::posix_time::seconds(s); }
74 inline time_duration milliseconds(int s) { return boost::posix_time::milliseconds(s); }
75 inline time_duration microsec(int s) { return boost::posix_time::microsec(s); }
76 inline time_duration minutes(int s) { return boost::posix_time::minutes(s); }
77 inline time_duration hours(int s) { return boost::posix_time::hours(s); }
79 inline int total_seconds(time_duration td)
80 { return td.total_seconds(); }
81 inline int total_milliseconds(time_duration td)
82 { return td.total_milliseconds(); }
83 inline boost::int64_t total_microseconds(time_duration td)
84 { return td.total_microseconds(); }
88 #else
90 #if BOOST_VERSION < 103500
91 #include <asio/time_traits.hpp>
92 #else
93 #include <boost/asio/time_traits.hpp>
94 #endif
95 #include <boost/cstdint.hpp>
96 #include "libtorrent/assert.hpp"
98 namespace libtorrent
100 // libtorrent time_duration type
101 struct time_duration
103 time_duration() {}
104 time_duration operator/(int rhs) const { return time_duration(diff / rhs); }
105 explicit time_duration(boost::int64_t d) : diff(d) {}
106 time_duration& operator-=(time_duration const& c) { diff -= c.diff; return *this; }
107 time_duration& operator+=(time_duration const& c) { diff += c.diff; return *this; }
108 time_duration operator+(time_duration const& c) { return time_duration(diff + c.diff); }
109 boost::int64_t diff;
112 inline bool is_negative(time_duration dt) { return dt.diff < 0; }
113 inline bool operator<(time_duration lhs, time_duration rhs)
114 { return lhs.diff < rhs.diff; }
115 inline bool operator<=(time_duration lhs, time_duration rhs)
116 { return lhs.diff <= rhs.diff; }
117 inline bool operator>(time_duration lhs, time_duration rhs)
118 { return lhs.diff > rhs.diff; }
119 inline bool operator>=(time_duration lhs, time_duration rhs)
120 { return lhs.diff >= rhs.diff; }
122 // libtorrent time type
123 struct ptime
125 ptime() {}
126 explicit ptime(boost::int64_t t): time(t) {}
127 ptime& operator+=(time_duration rhs) { time += rhs.diff; return *this; }
128 ptime& operator-=(time_duration rhs) { time -= rhs.diff; return *this; }
129 boost::int64_t time;
132 inline bool operator>(ptime lhs, ptime rhs)
133 { return lhs.time > rhs.time; }
134 inline bool operator>=(ptime lhs, ptime rhs)
135 { return lhs.time >= rhs.time; }
136 inline bool operator<=(ptime lhs, ptime rhs)
137 { return lhs.time <= rhs.time; }
138 inline bool operator<(ptime lhs, ptime rhs)
139 { return lhs.time < rhs.time; }
140 inline bool operator!=(ptime lhs, ptime rhs)
141 { return lhs.time != rhs.time;}
142 inline bool operator==(ptime lhs, ptime rhs)
143 { return lhs.time == rhs.time;}
144 inline time_duration operator-(ptime lhs, ptime rhs)
145 { return time_duration(lhs.time - rhs.time); }
146 inline ptime operator+(ptime lhs, time_duration rhs)
147 { return ptime(lhs.time + rhs.diff); }
148 inline ptime operator+(time_duration lhs, ptime rhs)
149 { return ptime(rhs.time + lhs.diff); }
150 inline ptime operator-(ptime lhs, time_duration rhs)
151 { return ptime(lhs.time - rhs.diff); }
153 ptime time_now();
154 inline ptime min_time() { return ptime(0); }
155 inline ptime max_time() { return ptime((std::numeric_limits<boost::int64_t>::max)()); }
156 int total_seconds(time_duration td);
157 int total_milliseconds(time_duration td);
158 boost::int64_t total_microseconds(time_duration td);
161 // asio time_traits
162 #if BOOST_VERSION >= 103500
163 namespace boost {
164 #endif
165 namespace asio
167 template<>
168 struct time_traits<libtorrent::ptime>
170 typedef libtorrent::ptime time_type;
171 typedef libtorrent::time_duration duration_type;
172 static time_type now()
173 { return time_type(libtorrent::time_now()); }
174 static time_type add(time_type t, duration_type d)
175 { return time_type(t.time + d.diff);}
176 static duration_type subtract(time_type t1, time_type t2)
177 { return duration_type(t1 - t2); }
178 static bool less_than(time_type t1, time_type t2)
179 { return t1 < t2; }
180 static boost::posix_time::time_duration to_posix_duration(
181 duration_type d)
182 { return boost::posix_time::microseconds(libtorrent::total_microseconds(d)); }
185 #if BOOST_VERSION >= 103500
187 #endif
189 #if defined(__MACH__)
191 #include <mach/mach_time.h>
192 #include <boost/cstdint.hpp>
193 #include "libtorrent/assert.hpp"
195 // high precision timer for darwin intel and ppc
197 namespace libtorrent
199 namespace aux
201 inline boost::int64_t absolutetime_to_microseconds(boost::int64_t at)
203 static mach_timebase_info_data_t timebase_info = {0,0};
204 if (timebase_info.denom == 0)
205 mach_timebase_info(&timebase_info);
206 // make sure we don't overflow
207 TORRENT_ASSERT((at >= 0 && at >= at / 1000 * timebase_info.numer / timebase_info.denom)
208 || (at < 0 && at < at / 1000 * timebase_info.numer / timebase_info.denom));
209 return at / 1000 * timebase_info.numer / timebase_info.denom;
212 inline boost::int64_t microseconds_to_absolutetime(boost::int64_t ms)
214 static mach_timebase_info_data_t timebase_info = {0,0};
215 if (timebase_info.denom == 0)
217 mach_timebase_info(&timebase_info);
218 TORRENT_ASSERT(timebase_info.numer > 0);
219 TORRENT_ASSERT(timebase_info.denom > 0);
221 // make sure we don't overflow
222 TORRENT_ASSERT((ms >= 0 && ms <= ms * timebase_info.denom / timebase_info.numer * 1000)
223 || (ms < 0 && ms > ms * timebase_info.denom / timebase_info.numer * 1000));
224 return ms * timebase_info.denom / timebase_info.numer * 1000;
228 inline int total_seconds(time_duration td)
230 return aux::absolutetime_to_microseconds(td.diff)
231 / 1000000;
233 inline int total_milliseconds(time_duration td)
235 return aux::absolutetime_to_microseconds(td.diff)
236 / 1000;
238 inline boost::int64_t total_microseconds(time_duration td)
240 return aux::absolutetime_to_microseconds(td.diff);
243 inline ptime time_now() { return ptime(mach_absolute_time()); }
245 inline time_duration microsec(boost::int64_t s)
247 return time_duration(aux::microseconds_to_absolutetime(s));
249 inline time_duration milliseconds(boost::int64_t s)
251 return time_duration(aux::microseconds_to_absolutetime(s * 1000));
253 inline time_duration seconds(boost::int64_t s)
255 return time_duration(aux::microseconds_to_absolutetime(s * 1000000));
257 inline time_duration minutes(boost::int64_t s)
259 return time_duration(aux::microseconds_to_absolutetime(s * 1000000 * 60));
261 inline time_duration hours(boost::int64_t s)
263 return time_duration(aux::microseconds_to_absolutetime(s * 1000000 * 60 * 60));
267 #elif defined(_WIN32)
269 #ifndef WIN32_LEAN_AND_MEAN
270 #define WIN32_LEAN_AND_MEAN
271 #endif
272 #include <windows.h>
273 #include "libtorrent/assert.hpp"
275 namespace libtorrent
277 namespace aux
279 inline boost::int64_t performance_counter_to_microseconds(boost::int64_t pc)
281 static LARGE_INTEGER performace_counter_frequency = {0,0};
282 if (performace_counter_frequency.QuadPart == 0)
283 QueryPerformanceFrequency(&performace_counter_frequency);
285 #ifndef NDEBUG
286 // make sure we don't overflow
287 boost::int64_t ret = (pc * 1000 / performace_counter_frequency.QuadPart) * 1000;
288 TORRENT_ASSERT((pc >= 0 && pc >= ret) || (pc < 0 && pc < ret));
289 #endif
290 return (pc * 1000 / performace_counter_frequency.QuadPart) * 1000;
293 inline boost::int64_t microseconds_to_performance_counter(boost::int64_t ms)
295 static LARGE_INTEGER performace_counter_frequency = {0,0};
296 if (performace_counter_frequency.QuadPart == 0)
297 QueryPerformanceFrequency(&performace_counter_frequency);
298 #ifndef NDEBUG
299 // make sure we don't overflow
300 boost::int64_t ret = (ms / 1000) * performace_counter_frequency.QuadPart / 1000;
301 TORRENT_ASSERT((ms >= 0 && ms <= ret)
302 || (ms < 0 && ms > ret));
303 #endif
304 return (ms / 1000) * performace_counter_frequency.QuadPart / 1000;
308 inline int total_seconds(time_duration td)
310 return int(aux::performance_counter_to_microseconds(td.diff)
311 / 1000000);
313 inline int total_milliseconds(time_duration td)
315 return int(aux::performance_counter_to_microseconds(td.diff)
316 / 1000);
318 inline boost::int64_t total_microseconds(time_duration td)
320 return aux::performance_counter_to_microseconds(td.diff);
323 inline ptime time_now()
325 LARGE_INTEGER now;
326 QueryPerformanceCounter(&now);
327 return ptime(now.QuadPart);
330 inline time_duration microsec(boost::int64_t s)
332 return time_duration(aux::microseconds_to_performance_counter(s));
334 inline time_duration milliseconds(boost::int64_t s)
336 return time_duration(aux::microseconds_to_performance_counter(
337 s * 1000));
339 inline time_duration seconds(boost::int64_t s)
341 return time_duration(aux::microseconds_to_performance_counter(
342 s * 1000000));
344 inline time_duration minutes(boost::int64_t s)
346 return time_duration(aux::microseconds_to_performance_counter(
347 s * 1000000 * 60));
349 inline time_duration hours(boost::int64_t s)
351 return time_duration(aux::microseconds_to_performance_counter(
352 s * 1000000 * 60 * 60));
357 #elif defined(_POSIX_MONOTONIC_CLOCK) && _POSIX_MONOTONIC_CLOCK >= 0
359 #include <time.h>
360 #include "libtorrent/assert.hpp"
362 namespace libtorrent
364 inline int total_seconds(time_duration td)
366 return td.diff / 1000000;
368 inline int total_milliseconds(time_duration td)
370 return td.diff / 1000;
372 inline boost::int64_t total_microseconds(time_duration td)
374 return td.diff;
377 inline ptime time_now()
379 timespec ts;
380 clock_gettime(CLOCK_MONOTONIC, &ts);
381 return ptime(boost::int64_t(ts.tv_sec) * 1000000 + ts.tv_nsec / 1000);
384 inline time_duration microsec(boost::int64_t s)
386 return time_duration(s);
388 inline time_duration milliseconds(boost::int64_t s)
390 return time_duration(s * 1000);
392 inline time_duration seconds(boost::int64_t s)
394 return time_duration(s * 1000000);
396 inline time_duration minutes(boost::int64_t s)
398 return time_duration(s * 1000000 * 60);
400 inline time_duration hours(boost::int64_t s)
402 return time_duration(s * 1000000 * 60 * 60);
407 #endif
409 #endif
411 #endif