File: _timer.py

package info (click to toggle)
python-expyriment 0.7.0%2Bgit34-g55a4e7e-3.2
  • links: PTS, VCS
  • area: main
  • in suites: stretch
  • size: 1,504 kB
  • ctags: 2,094
  • sloc: python: 12,766; makefile: 150
file content (114 lines) | stat: -rw-r--r-- 3,753 bytes parent folder | download | duplicates (2)
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
"""A high-resolution monotonic timer

This module provides a high-resolution timer via the function get_time()

Thanks to Luca Filippin for the code examples.

Credits and references:
      http://stackoverflow.com/questions/1205722/how-do-i-get-monotonic-time-durations-in-python
      http://stackoverflow.com/questions/1824399/get-mach-absolute-time-uptime-in-nanoseconds-in-python
      https://mail.python.org/pipermail/python-dev/2009-October/093173.html
"""

__author__ = 'Florian Krause <florian@expyriment.org>, \
Oliver Lindemann <oliver@expyriment.org>'
__version__ = '0.7.0'
__revision__ = '55a4e7e'
__date__ = 'Wed Mar 26 14:33:37 2014 +0100'

try:
    import ctypes
except:
    ctypes = None  # Does not exist on Android
import os
from sys import platform

_use_time_module = False

if platform == 'darwin':
    # MAC
    try:
        class _TimeBase(ctypes.Structure):
            _fields_ = [
                ('numer', ctypes.c_uint),
                ('denom', ctypes.c_uint)
            ]

        _libsys_c = ctypes.CDLL('/usr/lib/system/libsystem_c.dylib')
        _libsys_kernel = ctypes.CDLL('/usr/lib/system/libsystem_kernel.dylib')
        _mac_abs_time = _libsys_c.mach_absolute_time
        _mac_timebase_info = _libsys_kernel.mach_timebase_info
        _time_base = _TimeBase()
        if (_mac_timebase_info(ctypes.pointer(_time_base)) != 0):
            _use_time_module = True

        def get_time():
            """Get high-resolution monotonic time stamp (float) """
            _mac_abs_time.restype = ctypes.c_ulonglong
            return float(_mac_abs_time()) * _time_base.numer / (_time_base.denom * 1e9)
        get_time()
    except:
        _use_time_module = True

elif platform.startswith('linux'):
    # real OS
    _CLOCK_MONOTONIC = 4  # actually CLOCK_MONOTONIC_RAW see <linux/time.h>

    try:
        class _TimeSpec(ctypes.Structure):
            _fields_ = [
                ('tv_sec', ctypes.c_long),
                ('tv_nsec', ctypes.c_long)
            ]

        _librt = ctypes.CDLL('librt.so.1', use_errno=True)
        _clock_gettime = _librt.clock_gettime
        _clock_gettime.argtypes = [ctypes.c_int, ctypes.POINTER(_TimeSpec)]

        def get_time():
            """Get high-resolution monotonic time stamp (float) """
            t = _TimeSpec()
            if _clock_gettime(_CLOCK_MONOTONIC, ctypes.pointer(t)) != 0:
                errno_ = ctypes.get_errno()
                raise OSError(errno_, os.strerror(errno_))
            return t.tv_sec + t.tv_nsec * 1e-9
        get_time()
    except:
        _use_time_module = True

elif platform == 'win32':
    # win32. Code adapted from the psychopy.core.clock source code.
    try:
        _fcounter = ctypes.c_int64()
        _qpfreq = ctypes.c_int64()
        ctypes.windll.Kernel32.QueryPerformanceFrequency(ctypes.byref(_qpfreq))
        _qpfreq = float(_qpfreq.value)
        _winQPC = ctypes.windll.Kernel32.QueryPerformanceCounter

        def get_time():
            """Get high-resolution monotonic time stamp (float) """
            _winQPC(ctypes.byref(_fcounter))
            return  _fcounter.value/_qpfreq
        get_time()
    except:
        _use_time_module = True
else:
    # Android or something else
    _use_time_module = True


if _use_time_module:
    import time
    warn_message = "Failed to initialize monotonic timer. Python's time module will be use."
    print("Warning: " + warn_message)
    if platform == 'win32':
        def get_time():
            """Get high-resolution time stamp (float) """
            return time.clock()
    else:
        def get_time():
            """Get high-resolution time stamp (float) """
            return time.time()

if __name__ == "__main__":
    print get_time()