1 //  posix/chrono.cpp  --------------------------------------------------------------//
2 
3 //  Copyright Beman Dawes 2008
4 //  Copyright Vicente J. Botet Escriba 2009
5 
6 //  Distributed under the Boost Software License, Version 1.0.
7 //  See http://www.boost.org/LICENSE_1_0.txt
8 
9 //----------------------------------------------------------------------------//
10 //                                POSIX                                     //
11 //----------------------------------------------------------------------------//
12 
13 #include <time.h>  // for clock_gettime
14 #include <boost/assert.hpp>
15 #include <boost/predef/os.h>
16 
17 namespace boost
18 {
19 namespace chrono
20 {
21 
now()22   system_clock::time_point system_clock::now() BOOST_NOEXCEPT
23   {
24     timespec ts;
25     if ( ::clock_gettime( CLOCK_REALTIME, &ts ) )
26     {
27       BOOST_ASSERT(0 && "Boost::Chrono - Internal Error");
28     }
29 
30     return time_point(duration(
31       static_cast<system_clock::rep>( ts.tv_sec ) * 1000000000 + ts.tv_nsec));
32   }
33 
34 #if !defined BOOST_CHRONO_DONT_PROVIDE_HYBRID_ERROR_HANDLING
now(system::error_code & ec)35   system_clock::time_point system_clock::now(system::error_code & ec)
36   {
37     timespec ts;
38     if ( ::clock_gettime( CLOCK_REALTIME, &ts ) )
39     {
40         if (::boost::chrono::is_throws(ec))
41         {
42             boost::throw_exception(
43                     system::system_error(
44                             errno,
45                             ::boost::system::system_category(),
46                             "chrono::system_clock" ));
47         }
48         else
49         {
50             ec.assign( errno, ::boost::system::system_category() );
51             return time_point();
52         }
53     }
54 
55     if (!::boost::chrono::is_throws(ec))
56     {
57         ec.clear();
58     }
59     return time_point(duration(
60       static_cast<system_clock::rep>( ts.tv_sec ) * 1000000000 + ts.tv_nsec));
61   }
62 #endif
63 
to_time_t(const system_clock::time_point & t)64   std::time_t system_clock::to_time_t(const system_clock::time_point& t) BOOST_NOEXCEPT
65   {
66       return static_cast<std::time_t>( t.time_since_epoch().count() / 1000000000 );
67   }
68 
from_time_t(std::time_t t)69   system_clock::time_point system_clock::from_time_t(std::time_t t) BOOST_NOEXCEPT
70   {
71       return time_point(duration(static_cast<system_clock::rep>(t) * 1000000000));
72   }
73 
74 #ifdef BOOST_CHRONO_HAS_CLOCK_STEADY
75 
now()76   steady_clock::time_point steady_clock::now() BOOST_NOEXCEPT
77   {
78     timespec ts;
79 #if BOOST_OS_CYGWIN
80     // lack of thread safety in high resolution timer initialization
81     // can lead to a timespec of zero without an error; was reported
82     // to the cygwin mailing list and can be removed once fixed
83     do
84     {
85 #endif
86       if ( ::clock_gettime( CLOCK_MONOTONIC, &ts ) )
87       {
88         BOOST_ASSERT(0 && "Boost::Chrono - Internal Error");
89       }
90 #if BOOST_OS_CYGWIN
91     } while (ts.tv_sec == 0 && ts.tv_nsec == 0);
92 #endif
93     return time_point(duration(
94       static_cast<steady_clock::rep>( ts.tv_sec ) * 1000000000 + ts.tv_nsec));
95   }
96 
97 #if !defined BOOST_CHRONO_DONT_PROVIDE_HYBRID_ERROR_HANDLING
now(system::error_code & ec)98   steady_clock::time_point steady_clock::now(system::error_code & ec)
99   {
100     timespec ts;
101 #if BOOST_OS_CYGWIN
102     // lack of thread safety in high resolution timer initialization
103     // can lead to a timespec of zero without an error; was reported
104     // to the cygwin mailing list and can be removed once fixed
105     do
106     {
107 #endif
108       if ( ::clock_gettime( CLOCK_MONOTONIC, &ts ) )
109       {
110         if (::boost::chrono::is_throws(ec))
111         {
112             boost::throw_exception(
113                     system::system_error(
114                             errno,
115                             ::boost::system::system_category(),
116                             "chrono::steady_clock" ));
117         }
118         else
119         {
120             ec.assign( errno, ::boost::system::system_category() );
121             return time_point();
122         }
123       }
124 #if BOOST_OS_CYGWIN
125     } while (ts.tv_sec == 0 && ts.tv_nsec == 0);
126 #endif
127 
128     if (!::boost::chrono::is_throws(ec))
129     {
130         ec.clear();
131     }
132     return time_point(duration(
133       static_cast<steady_clock::rep>( ts.tv_sec ) * 1000000000 + ts.tv_nsec));
134   }
135 #endif
136 #endif
137 
138 }  // namespace chrono
139 }  // namespace boost
140 
141 
142