svn update: 60286 (latest:60286)
[profile/ivi/ecore.git] / src / lib / ecore / ecore_time.c
1 #ifdef HAVE_CONFIG_H
2 # include <config.h>
3 #endif
4
5 #include <stdlib.h>
6
7 #ifdef HAVE_SYS_TIME_H
8 # include <sys/time.h>
9 #endif
10
11 #ifdef HAVE_EVIL
12 # include <Evil.h>
13 #endif
14
15 #if defined(__APPLE__) && defined(__MACH__)
16 # include <mach/mach_time.h>
17 #endif
18
19 #include "Ecore.h"
20 #include "ecore_private.h"
21
22 #include <time.h>
23
24 #ifdef HAVE_CLOCK_GETTIME
25 static clockid_t _ecore_time_clock_id = -1;
26 #elif defined(__APPLE__) && defined(__MACH__)
27 static double _ecore_time_clock_conversion = 1e-9;
28 #endif
29 double _ecore_time_loop_time = -1.0;
30
31 /**
32  * @addtogroup Ecore_Group Ecore - Main Loop and Job Functions.
33  *
34  * @{
35  */
36
37 /**
38  * @addtogroup Ecore_Time_Group Ecore Time functions
39  *
40  * @{
41  */
42
43 /**
44  * Retrieves the current system time as a floating point value in seconds.
45  *
46  * This uses a monotonic clock and thus never goes back in time while
47  * machine is live (even if user changes time or timezone changes,
48  * however it may be reset whenever the machine is restarted).
49  *
50  * @see ecore_loop_time_get().
51  * @see ecore_time_unix_get().
52  *
53  * @return The number of seconds. Start time is not defined (it may be
54  *         when the machine was booted, unix time, etc), all it is
55  *         defined is that it never goes backwards (unless you got big critical
56  *         messages when the application started).
57  */
58 EAPI double
59 ecore_time_get(void)
60 {
61 #ifdef HAVE_CLOCK_GETTIME
62    struct timespec t;
63
64    if (EINA_UNLIKELY(_ecore_time_clock_id < 0))
65       return ecore_time_unix_get();
66
67    if (EINA_UNLIKELY(clock_gettime(_ecore_time_clock_id, &t)))
68      {
69         CRIT("Cannot get current time.");
70         /* Try to at least return the latest value retrieved*/
71         return _ecore_time_loop_time;
72      }
73
74    return (double)t.tv_sec + (((double)t.tv_nsec) / 1000000000.0);
75 #elif defined(HAVE_EVIL)
76    return evil_time_get();
77 #elif defined(__APPLE__) && defined(__MACH__)
78    return _ecore_time_clock_conversion * (double) mach_absolute_time();
79 #else
80    return ecore_time_unix_get();
81 #endif
82 }
83
84 /**
85  * Retrieves the current UNIX time as a floating point value in seconds.
86  *
87  * @see ecore_time_get().
88  * @see ecore_loop_time_get().
89  *
90  * @return  The number of seconds since 12.00AM 1st January 1970.
91  */
92 EAPI double
93 ecore_time_unix_get(void)
94 {
95 #ifdef HAVE_GETTIMEOFDAY
96    struct timeval timev;
97
98    gettimeofday(&timev, NULL);
99    return (double)timev.tv_sec + (((double)timev.tv_usec) / 1000000);
100 #else
101 # error "Your platform isn't supported yet"
102 #endif
103 }
104
105 /**
106  * Retrieves the time at which the last loop stopped waiting for timeouts or
107  * events.
108  *
109  * This gets the time that the main loop ceased waiting for timouts and/or
110  * events to come in or for signals or any other interrupt source. This should
111  * be considered a reference point for all time based activity that should
112  * calculate its timepoint from the return of ecore_loop_time_get(). Use this
113  * UNLESS you absolutely must get the current actual timepoint - then use
114  * ecore_time_get(). Note that this time is meant to be used as relative to
115  * other times obtained on this run. If you need absolute time references, use
116  * ecore_time_unix_get() instead.
117  *
118  * This function can be called before any loop has ever been run, but either
119  * ecore_init() or ecore_time_get() must have been called once.
120  *
121  * @return The number of seconds. Start time is not defined (it may be
122  *         when the machine was booted, unix time, etc), all it is
123  *         defined is that it never goes backwards (unless you got big critical
124  *         messages when the application started).
125  */
126 EAPI double
127 ecore_loop_time_get(void)
128 {
129    return _ecore_time_loop_time;
130 }
131
132 /**
133  * @}
134  */
135
136 /**
137  * @}
138  */
139
140
141 /**********************   Internal methods   ********************************/
142
143 /* TODO: Documentation says "All  implementations  support  the  system-wide
144  * real-time clock, which is identified by CLOCK_REALTIME. Check if the fallback
145  * to unix time (without specifying the resolution) might be removed
146  */
147 void
148 _ecore_time_init(void)
149 {
150 #ifdef HAVE_CLOCK_GETTIME
151    struct timespec t;
152
153    if (_ecore_time_clock_id != -1) return;
154
155    if (!clock_gettime(CLOCK_MONOTONIC, &t))
156      {
157         _ecore_time_clock_id = CLOCK_MONOTONIC;
158         DBG("using CLOCK_MONOTONIC.");
159      }
160    else if (!clock_gettime(CLOCK_REALTIME, &t))
161      {
162         /* may go backwards */
163         _ecore_time_clock_id = CLOCK_REALTIME;
164         WRN("CLOCK_MONOTONIC not available. Fallback to CLOCK_REALTIME.");
165      }
166    else
167      {
168         _ecore_time_clock_id = -2;
169         CRIT("Cannot get a valid clock_gettime() clock id! "
170              "Fallback to unix time.");
171      }
172 #else
173 # ifndef HAVE_EVIL
174 #  if defined(__APPLE__) && defined(__MACH__)
175    mach_timebase_info_data_t info;
176    kern_return_t err = mach_timebase_info(&info);
177    if (err == 0)
178      {
179         _ecore_time_clock_conversion = 1e-9 * (double) info.numer / (double) info.denom;
180      }
181    else
182      {
183         WRN("Unable to get timebase info. Fallback to nanoseconds.");
184      }
185 #  else
186 #  warning "Your platform isn't supported yet"
187    CRIT("Platform does not support clock_gettime. "
188         "Fallback to unix time.");
189 #  endif
190 # endif
191 #endif
192
193    _ecore_time_loop_time = ecore_time_get();
194 }