1
// -*- C++ -*- Time-stamp: <2012-04-16 17:29:39 ptr>
2
3
/*
4
 * Copyright (c) 2002, 2006-2011
5
 * Petr Ovtchenkov
6
 *
7
 * This material is provided "as is", with absolutely no warranty expressed
8
 * or implied. Any use is at your own risk.
9
 *
10
 * Permission to use or copy this software for any purpose is hereby granted
11
 * without fee, provided the above notices are retained on all copies.
12
 * Permission to modify the code and to distribute modified code is granted,
13
 * provided the above notices are retained, and a notice that the code was
14
 * modified is included with the above copyright notice.
15
 *
16
 * Derived from original <misc/chrono> of 'complement' project
17
 * [http://complement.sourceforge.net]
18
 * to make it close to JTC1/SC22/WG21 C++ 0x working draft
19
 * [http://www.open-std.org/Jtc1/sc22/wg21/docs/papers/2011/n3291.pdf]
20
 */
21
22
#ifndef __STLP_CHRONO
23
#define __STLP_CHRONO
24
25
#include <type_traits>
26
#include <ratio>
27
#include <functional>
28
#include <limits>
29
#include <ctime>
30
31
#ifndef _STLP_OUTERMOST_HEADER_ID
32
#  define _STLP_OUTERMOST_HEADER_ID 0x4
33
#  include <stl/_cprolog.h>
34
#endif
35
36
_STLP_BEGIN_NAMESPACE
37
38
namespace chrono {
39
40
// customization traits
41
42
template <class Rep>
43
struct treat_as_floating_point :
44
        public _STLP_STD::is_floating_point<Rep>
45
{
46
};
47
48
template <class Rep, class Period>
49
class duration;
50
51
namespace detail {
52
53
template <class T>
54
struct __is_duration :
55
        public _STLP_STD::false_type
56
{ };
57
58
template <class R, class P>
59
struct __is_duration<duration<R,P> > :
60
        public _STLP_STD::true_type
61
{ };
62
63
} // namespace detail
64
65
namespace detail {
66
67
template <class ToDuration, class CF, class CR, bool N, bool D>
68
struct _duration_cast
69
{
70
    template <class Rep, class Period>
71
    static ToDuration _cast( const duration<Rep, Period>& d )
72
      {
73
        return ToDuration(static_cast<typename ToDuration::rep&&>(d.count() * CF::num / CF::den) );
74
      }
75
};
76
77
template <class ToDuration, class CF, class CR>
78
struct _duration_cast<ToDuration,CF,CR,true,true>
79
{
80
    template <class Rep, class Period>
81
    static ToDuration _cast( const duration<Rep, Period>& d )
82
      {
83
        return ToDuration(static_cast<typename ToDuration::rep&&>(d.count()) );
84
      }
85
};
86
87
template <class ToDuration, class CF, class CR>
88
struct _duration_cast<ToDuration,CF,CR,false,true>
89
{
90
    template <class Rep, class Period>
91
    static ToDuration _cast( const duration<Rep, Period>& d )
92
      {
93
        return ToDuration(static_cast<typename ToDuration::rep&&>(d.count() * CF::num) );
94
      }
95
};
96
97
template <class ToDuration, class CF, class CR>
98
struct _duration_cast<ToDuration,CF,CR,true,false>
99
{
100
    template <class Rep, class Period>
101
    static ToDuration _cast( const duration<Rep, Period>& d )
102
      {
103
        return ToDuration(static_cast<typename ToDuration::rep&&>(d.count() / CF::den) );
104
      }
105
};
106
107
} // namespace detail
108
109
template <class ToDuration, class Rep, class Period>
110
constexpr typename enable_if<detail::__is_duration<ToDuration>::value,ToDuration>::type duration_cast( const duration<Rep, Period>& d )
111
{
112
  typedef ratio_divide<Period, typename ToDuration::period> _cf;
113
#ifdef _STLP_CPP_0X
114
  typedef typename _STLP_STD::common_type<typename ToDuration::rep, Rep, intmax_t>::type _cr;
115
#else
116
  typedef typename _STLP_STD::common_type<typename ToDuration::rep, Rep>::type _cr;
117
#endif
118
119
  return detail::_duration_cast<ToDuration,_cf,_cr,_cf::num == 1, _cf::den == 1>::_cast( d );
120
}
121
122
template <class Rep>
123
struct duration_values
124
{
125
    static constexpr Rep zero()
126
      { return Rep(0); }
127
    static constexpr Rep min()
128
      { return numeric_limits<Rep>::lowest(); }
129
    static constexpr Rep max()
130
      { return numeric_limits<Rep>::max(); }
131
};
132
133
template <class Rep, class Period = _STLP_STD::ratio<1> >
134
class duration
135
{
136
#ifdef _STLP_CPP_0X
137
    static_assert( !detail::__is_duration<Rep>::value, "rep can't be a duration" );
138
    static_assert( _STLP_STD::detail::__is_ratio<Period>::value, "period must be a ratio specialization");
139
    static_assert( Period::num > 0, "numerator must be positive" );
140
#endif
141
142
  public:
143
    typedef typename _STLP_STD::remove_reference<Rep>::type rep;
144
    typedef Period period;
145
146
  private:
147
    rep rep_;
148
149
  public:
150
    // 20.11.5.1, construct/copy/destroy:
151
#ifdef _STLP_CPP_0X
152
    constexpr duration() = default;
153
154
#if 0
155
    template <class Rep2, class =
156
              typename _STLP_STD::enable_if<_STLP_STD::is_arithmetic<Rep2>::value && _STLP_STD::is_convertible<Rep2,rep>::value &&
157
                                            (treat_as_floating_point<rep>::value || !treat_as_floating_point<Rep2>::value)>::type>
158
    constexpr explicit duration( const Rep2 r ) :
159
        rep_(static_cast<rep>(r))
160
      { }
161
#endif
162
163
    template <class Rep2, class =
164
              typename _STLP_STD::enable_if</* !_STLP_STD::is_arithmetic<Rep2>::value && */ _STLP_STD::is_convertible<Rep2,rep>::value &&
165
                                            (treat_as_floating_point<rep>::value || !treat_as_floating_point<Rep2>::value)>::type>
166
    constexpr explicit duration( const Rep2& r ) :
167
        rep_(static_cast<rep>(r))
168
      { }
169
170
    template <class Rep2, class Period2, class =
171
              typename _STLP_STD::enable_if<treat_as_floating_point<rep>::value ||
172
                                 ((ratio_divide<Period2,period>::den == 1) && !treat_as_floating_point<Rep2>::value)>::type>
173
    constexpr duration( const duration<Rep2, Period2>& d ) :
174
        rep_( duration_cast<duration>(d).count() )
175
      { }
176
177
    ~duration() = default;
178
    duration( const duration& ) = default;
179
180
    duration& operator =( const duration& ) = default;
181
#else // _STLP_CPP_0X
182
    duration()
183
      { }
184
    template <class Rep2>
185
    explicit duration( const Rep2& r ) :
186
        rep_(static_cast<rep>(r))
187
      { }
188
    template <class Rep2, class Period2>
189
    duration( const duration<Rep2, Period2>& d ) :
190
        rep_( duration_cast<duration>(d).count() )
191
      { }
192
    // ~duration() = default;
193
    // duration( const duration& ) = default;
194
#endif // _STLP_CPP_0X
195
196
    // 20.11.5.2, observer:
197
    constexpr rep count() const
198
      { return rep_; }
199
200
    // 20.11.5.3, arithmetic:
201
    constexpr duration operator +() const
202
      { return *this; }
203
    constexpr duration operator -() const
204
      { return duration( -rep_ ); }
205
    duration& operator ++()
206
      { ++rep_; return *this; }
207
    duration operator ++(int)
208
      { return duration( rep_++ ); }
209
    duration& operator --()
210
      { --rep_; return *this; }
211
    duration operator --(int)
212
      { return duration( rep_-- ); }
213
    duration& operator +=( const duration& d )
214
      { rep_ += d.count(); return *this; }
215
    duration& operator -=( const duration& d )
216
      { rep_ -= d.count(); return *this; }
217
    duration& operator *=(const rep& rhs)
218
      { rep_ *= rhs; return *this; }
219
    duration& operator /=( const rep& rhs )
220
      { rep_ /= rhs; return *this; }
221
    duration& operator %=(const rep& rhs)
222
      { rep_ %= rhs; return *this; }
223
    duration& operator %=(const duration& rhs)
224
      { rep_ %= rhs.count(); return *this; }
225
226
    // 20.11.5.4, special values:
227
    static constexpr duration zero()
228
      { return duration( duration_values<rep>::zero() ); }
229
    static constexpr duration min()
230
      { return duration( duration_values<rep>::min() ); }
231
    static constexpr duration max()
232
      { return duration( duration_values<rep>::max() ); }
233
};
234
235
template <class Clock, class Duration = typename Clock::duration>
236
class time_point
237
{
238
  public:
239
    typedef Clock clock;
240
    typedef Duration duration;
241
    typedef typename duration::rep rep;
242
    typedef typename duration::period period;
243
244
  private:
245
    duration d_;
246
247
  public:
248
    // 20.11.6.1, construct:
249
    time_point() : // has value epoch
250
        d_( duration::zero() )
251
      { }
252
    explicit time_point( const duration& d ) : // same as time_point() + d
253
        d_( d )
254
      { }
255
256
#ifdef _STLP_CPP_0X
257
    template <class Duration2, class = typename _STLP_STD::enable_if<_STLP_STD::is_convertible<Duration2,duration>::value >::type>
258
    time_point( const time_point<clock, Duration2>& t ) :
259
        d_( t.time_since_epoch() /* t.d_ */ )
260
      { }
261
#else // _STLP_CPP_0X
262
    template <class Duration2>
263
    time_point( const time_point<clock, Duration2>& t ) :
264
        d_( t.time_since_epoch() /* t.d_ */ )
265
      { }
266
#endif // _STLP_CPP_0X
267
268
    // 20.11.6.2, observer:
269
    duration time_since_epoch() const
270
      { return d_; }
271
272
    // 20.11.6.3, arithmetic:
273
    time_point& operator +=( const duration& d )
274
      { d_ += d; return *this; }
275
    time_point& operator -=( const duration& d )
276
      { d_ -= d; return *this; }
277
278
    // 20.11.6.4, special values:
279
    static constexpr time_point min()
280
      { return time_point( duration::min() ); }
281
    static constexpr time_point max()
282
      { return time_point( duration::max() ); }
283
};
284
285
} // namespace chrono
286
287
template <class Rep1, class Period1, class Rep2, class Period2>
288
struct common_type<chrono::duration<Rep1, Period1>, chrono::duration<Rep2, Period2> >
289
{
290
    typedef chrono::duration<typename common_type<Rep1,Rep2>::type, ratio<_STLP_STD::detail::__gcd<Period1::num,Period2::num>::value, (Period1::den / _STLP_STD::detail::__gcd<Period1::den,Period2::den>::value) * Period2::den> > type;
291
};
292
293
template <class Clock, class Duration1, class Duration2>
294
struct common_type<chrono::time_point<Clock, Duration1>, chrono::time_point<Clock, Duration2> >
295
{
296
    typedef chrono::time_point<Clock,typename common_type<Duration1,Duration2>::type> type;
297
};
298
299
namespace chrono {
300
301
// duration arithmetic
302
303
template <class Rep1, class Period1, class Rep2, class Period2>
304
constexpr typename common_type<duration<Rep1, Period1>, duration<Rep2, Period2> >::type
305
operator +( const duration<Rep1, Period1>& lhs, const duration<Rep2, Period2>& rhs )
306
{
307
  typedef typename common_type<duration<Rep1, Period1>, duration<Rep2, Period2> >::type _ct;
308
  return _ct(_ct(lhs).count() + _ct(rhs).count());
309
}
310
311
template <class Rep1, class Period1, class Rep2, class Period2>
312
typename common_type<duration<Rep1, Period1>, duration<Rep2, Period2> >::type
313
constexpr operator -( const duration<Rep1, Period1>& lhs, const duration<Rep2, Period2>& rhs )
314
{
315
  typedef typename common_type<duration<Rep1, Period1>, duration<Rep2, Period2> >::type _ct;
316
  return _ct(_ct(lhs).count() - _ct(rhs).count());
317
}
318
319
namespace detail {
320
321
template <class Rep1, class Rep2, bool = is_convertible<Rep2, typename common_type<Rep1,Rep2>::type>::value>
322
struct _common_type
323
{
324
};
325
326
template <class Rep1, class Rep2>
327
struct _common_type<Rep1,Rep2,true>
328
{
329
    typedef typename common_type<Rep1,Rep2>::type type;
330
};
331
332
} // namespace detail
333
334
template <class Rep1, class Period, class Rep2>
335
constexpr duration<typename detail::_common_type<Rep1, Rep2>::type, Period>
336
operator *( const duration<Rep1, Period>& d, const Rep2& s )
337
{
338
  typedef duration<typename common_type<Rep1,Rep2>::type, Period> _ct;
339
340
  return _ct( _ct( d ).count() * s );
341
}
342
343
template <class Rep1, class Period, class Rep2>
344
constexpr duration<typename detail::_common_type<Rep2, Rep1>::type, Period>
345
operator *( const Rep1& s, const duration<Rep2, Period>& d )
346
{ return d * s; }
347
348
template <class Rep1, class Period, class Rep2>
349
constexpr duration<typename detail::_common_type<Rep1,typename enable_if<!detail::__is_duration<Rep2>::value,Rep2>::type>::type, Period>
350
operator /( const duration<Rep1, Period>& d, const Rep2& s )
351
{
352
  typedef duration<typename common_type<Rep1,Rep2>::type, Period> _ct;
353
354
  return _ct( _ct(d).count() / s );
355
}
356
357
template <class Rep1, class Period1, class Rep2, class Period2>
358
constexpr typename common_type<Rep1, Rep2>::type
359
operator /( const duration<Rep1, Period1>& lhs, const duration<Rep2, Period2>& rhs )
360
{
361
  typedef typename common_type<Rep1, Rep2>::type _ct;
362
363
  return _ct(lhs).count() / _ct(rhs).count();
364
}
365
366
template <class Rep1, class Period, class Rep2>
367
constexpr duration<typename detail::_common_type<Rep1, typename enable_if<!detail::__is_duration<Rep2>::value,Rep2>::type>::type, Period>
368
operator %( const duration<Rep1, Period>& d, const Rep2& s )
369
{
370
  typedef duration<typename common_type<Rep1,Rep2>::type, Period> _ct;
371
372
  return _ct( _ct(d).count() % s );
373
}
374
375
template <class Rep1, class Period1, class Rep2, class Period2>
376
constexpr typename common_type<duration<Rep1, Period1>, duration<Rep2, Period2> >::type
377
operator %( const duration<Rep1, Period1>& lhs, const duration<Rep2, Period2>& rhs )
378
{
379
  typedef typename common_type<duration<Rep1, Period1>, duration<Rep2, Period2> >::type _ct;
380
381
  return _ct( _ct(lhs).count() % _ct(rhs).count() );
382
}
383
384
// duration comparisons
385
386
template <class Rep1, class Period1, class Rep2, class Period2>
387
constexpr bool operator ==( const duration<Rep1, Period1>& lhs, const duration<Rep2, Period2>& rhs )
388
{
389
  typedef typename common_type<duration<Rep1, Period1>, duration<Rep2, Period2> >::type _ct;
390
391
  return _ct(lhs).count() == _ct(rhs).count();
392
}
393
394
template <class Rep1, class Period1, class Rep2, class Period2>
395
constexpr bool operator !=( const duration<Rep1, Period1>& lhs, const duration<Rep2, Period2>& rhs )
396
{
397
  return !(lhs == rhs);
398
}
399
400
template <class Rep1, class Period1, class Rep2, class Period2>
401
constexpr bool operator <( const duration<Rep1, Period1>& lhs, const duration<Rep2, Period2>& rhs )
402
{
403
  typedef typename common_type<duration<Rep1, Period1>, duration<Rep2, Period2> >::type _ct;
404
405
  return _ct(lhs).count() < _ct(rhs).count();
406
}
407
408
template <class Rep1, class Period1, class Rep2, class Period2>
409
constexpr bool operator <=( const duration<Rep1, Period1>& lhs, const duration<Rep2, Period2>& rhs )
410
{
411
  return !(rhs < lhs);
412
}
413
414
template <class Rep1, class Period1, class Rep2, class Period2>
415
constexpr bool operator >( const duration<Rep1, Period1>& lhs, const duration<Rep2, Period2>& rhs )
416
{
417
  return rhs < lhs;
418
}
419
420
template <class Rep1, class Period1, class Rep2, class Period2>
421
constexpr bool operator >=( const duration<Rep1, Period1>& lhs, const duration<Rep2, Period2>& rhs )
422
{
423
  return !(lhs < rhs);
424
}
425
426
// convenience typedefs
427
typedef duration<int64_t,  nano>    nanoseconds;
428
typedef duration<int64_t, micro>    microseconds;
429
typedef duration<int64_t, milli>    milliseconds;
430
typedef duration<int64_t>           seconds;
431
typedef duration<int, ratio<60> >   minutes;
432
typedef duration<int, ratio<3600> > hours;
433
434
// time_point arithmetic
435
436
template <class Clock, class Duration1, class Rep2, class Period2>
437
time_point<Clock, typename common_type<Duration1, duration<Rep2, Period2> >::type>
438
operator +(const time_point<Clock, Duration1>& lhs, const duration<Rep2, Period2>& rhs)
439
{
440
  typedef time_point<Clock, typename common_type<Duration1, duration<Rep2, Period2> >::type> _ct;
441
442
  return _ct(lhs) += rhs;
443
}
444
445
template <class Rep1, class Period1, class Clock, class Duration2>
446
time_point<Clock, typename common_type<duration<Rep1, Period1>, Duration2>::type>
447
operator +(const duration<Rep1, Period1>& lhs, const time_point<Clock, Duration2>& rhs)
448
{ return rhs + lhs; }
449
450
template <class Clock, class Duration1, class Rep2, class Period2>
451
time_point<Clock, typename common_type<Duration1, duration<Rep2, Period2> >::type>
452
operator -(const time_point<Clock, Duration1>& lhs, const duration<Rep2, Period2>& rhs)
453
{ return lhs + (-rhs); }
454
455
template <class Clock, class Duration1, class Duration2>
456
typename common_type<Duration1, Duration2>::type
457
operator -(const time_point<Clock, Duration1>& lhs, const time_point<Clock, Duration2>& rhs)
458
{ return lhs.time_since_epoch() - rhs.time_since_epoch(); }
459
460
// time_point comparisons
461
462
template <class Clock, class Duration1, class Duration2>
463
bool operator ==(const time_point<Clock, Duration1>& lhs, const time_point<Clock, Duration2>& rhs)
464
{ return lhs.time_since_epoch() == rhs.time_since_epoch(); }
465
466
template <class Clock, class Duration1, class Duration2>
467
bool operator !=(const time_point<Clock, Duration1>& lhs, const time_point<Clock, Duration2>& rhs)
468
{ return !(lhs == rhs); }
469
470
template <class Clock, class Duration1, class Duration2>
471
bool operator <(const time_point<Clock, Duration1>& lhs, const time_point<Clock, Duration2>& rhs)
472
{ return lhs.time_since_epoch() < rhs.time_since_epoch(); }
473
474
template <class Clock, class Duration1, class Duration2>
475
bool operator <=(const time_point<Clock, Duration1>& lhs, const time_point<Clock, Duration2>& rhs)
476
{ return !(rhs < lhs); }
477
478
template <class Clock, class Duration1, class Duration2>
479
bool operator >(const time_point<Clock, Duration1>& lhs, const time_point<Clock, Duration2>& rhs)
480
{ return rhs < lhs; }
481
482
template <class Clock, class Duration1, class Duration2>
483
bool operator >=(const time_point<Clock, Duration1>& lhs, const time_point<Clock, Duration2>& rhs)
484
{ return !(lhs < rhs); }
485
486
// time_point_cast
487
template <class ToDuration, class Clock, class Duration>
488
typename enable_if<detail::__is_duration<ToDuration>::value, time_point<Clock, ToDuration> >::type
489
time_point_cast( const time_point<Clock, Duration>& t )
490
{ return time_point<Clock, ToDuration>(duration_cast<ToDuration>(t.time_since_epoch())); }
491
492
// Clocks
493
494
class _STLP_CLASS_DECLSPEC system_clock
495
{
496
  public:
497
#ifdef __unix
498
    typedef chrono::nanoseconds duration;
499
    typedef duration::rep rep;
500
    typedef duration::period period;
501
#elif defined( WIN32 )
502
    typedef __int64 rep;
503
    typedef ratio<1LL, 10000000LL> period;
504
    typedef chrono::duration<rep, period> duration;
505
#endif
506
    typedef chrono::time_point<system_clock> time_point;
507
508
    static const bool is_steady;
509
510
    static time_point now() /* noexcept */ throw();
511
512
    static time_t to_time_t( const time_point& t ) /* noexcept */ throw();
513
    static time_point from_time_t( time_t t ) /* noexcept */ throw();
514
};
515
516
class _STLP_CLASS_DECLSPEC steady_clock
517
{
518
  public:
519
    typedef chrono::nanoseconds duration;
520
    typedef duration::rep rep;
521
    typedef duration::period period;
522
    typedef chrono::time_point<system_clock> time_point;
523
524
    static const bool is_steady;
525
526
    static time_point now() /* noexcept */ throw();
527
};
528
529
typedef system_clock high_resolution_clock;
530
531
} // namespace chrono
532
533
_STLP_END_NAMESPACE
534
535
#if (_STLP_OUTERMOST_HEADER_ID == 0x4)
536
#  include <stl/_epilog.h>
537
#  undef _STLP_OUTERMOST_HEADER_ID
538
#endif
539
540
#endif // __STLP_CHRONO