summaryrefslogtreecommitdiff
path: root/src/lib/ecore/ecore_time.c
blob: 9f039e2b592eb7abbc2c65d8e8d38861dcc90589 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif

#define EFL_LOOP_PROTECTED

#include <stdlib.h>
#include <sys/time.h>

#if defined(__APPLE__) && defined(__MACH__)
# include <mach/mach_time.h>
#endif

#include <time.h>

#ifdef _WIN32
# include <evil_private.h> /* gettimeofday */
#endif

#include "Ecore.h"
#include "ecore_private.h"

#if defined(_WIN32)
static LONGLONG _ecore_time_freq;
#elif defined (HAVE_CLOCK_GETTIME)
static clockid_t _ecore_time_clock_id;
static Eina_Bool _ecore_time_got_clock_id = EINA_FALSE;
#elif defined(__APPLE__) && defined(__MACH__)
static double _ecore_time_clock_conversion = 1e-9;
#endif

EAPI double
ecore_time_get(void)
{
#ifdef _WIN32
   LARGE_INTEGER count;

   QueryPerformanceCounter(&count);
   return (double)count.QuadPart/ (double)_ecore_time_freq;
#elif defined (HAVE_CLOCK_GETTIME)
   struct timespec t;

   if (EINA_UNLIKELY(!_ecore_time_got_clock_id))
     return ecore_time_unix_get();

   if (EINA_UNLIKELY(clock_gettime(_ecore_time_clock_id, &t)))
     {
        CRI("Cannot get current time");
        return 0.0;
     }

   return (double)t.tv_sec + (((double)t.tv_nsec) / 1000000000.0);
#elif defined(__APPLE__) && defined(__MACH__)
   return _ecore_time_clock_conversion * (double)mach_absolute_time();
#else
   return ecore_time_unix_get();
#endif
}

EAPI double
ecore_time_unix_get(void)
{
#ifdef HAVE_GETTIMEOFDAY
   struct timeval timev;

   gettimeofday(&timev, NULL);
   return (double)timev.tv_sec + (((double)timev.tv_usec) / 1000000);
#else
# error "Your platform isn't supported yet"
#endif
}

EAPI double
ecore_loop_time_get(void)
{
   return efl_loop_time_get(ML_OBJ);
}

EAPI void
ecore_loop_time_set(double t)
{
   efl_loop_time_set(ML_OBJ, t);
}

/*-********************   Internal methods   ********************************/

/* TODO: Documentation says "All  implementations  support  the  system-wide
 * real-time clock, which is identified by CLOCK_REALTIME. Check if the fallback
 * to unix time (without specifying the resolution) might be removed
 */
void
_ecore_time_init(void)
{
#if defined(_WIN32)
   LARGE_INTEGER freq;

   QueryPerformanceFrequency(&freq);
   _ecore_time_freq = freq.QuadPart;
#elif defined(HAVE_CLOCK_GETTIME)
   struct timespec t;

   if (_ecore_time_got_clock_id) return;

   if (!clock_gettime(CLOCK_MONOTONIC, &t))
     {
        _ecore_time_clock_id = CLOCK_MONOTONIC;
        _ecore_time_got_clock_id = EINA_TRUE;
        DBG("using CLOCK_MONOTONIC");
     }
   else if (!clock_gettime(CLOCK_REALTIME, &t))
     {
        // may go backwards
        _ecore_time_clock_id = CLOCK_REALTIME;
        _ecore_time_got_clock_id = EINA_TRUE;
        WRN("CLOCK_MONOTONIC not available. Fallback to CLOCK_REALTIME");
     }
   else
     CRI("Cannot get a valid clock_gettime() clock id! Fallback to unix time");
#else
# if defined(__APPLE__) && defined(__MACH__)
   mach_timebase_info_data_t info;
   kern_return_t err = mach_timebase_info(&info);
   if (err == 0)
     _ecore_time_clock_conversion = 1e-9 * (double)info.numer / (double)info.denom;
   else
     WRN("Unable to get timebase info. Fallback to nanoseconds");
# else
#  warning "Your platform isn't supported yet"
   CRI("Platform does not support clock_gettime. Fallback to unix time");
# endif
#endif
   ecore_loop_time_set(ecore_time_get());
}