-
Notifications
You must be signed in to change notification settings - Fork 4
Expand file tree
/
Copy pathcTimer.c
More file actions
142 lines (121 loc) · 3.51 KB
/
Copy pathcTimer.c
File metadata and controls
142 lines (121 loc) · 3.51 KB
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
135
136
137
138
139
140
141
142
/*
* File: cTimer.c
* Author: Russ Porosky
*
* Created on May 3 2012
*/
#include "Python.h"
#if PY_MAJOR_VERSION >= 3
#define MOD_ERROR_VAL NULL
#define MOD_SUCCESS_VAL(val) val
#define MOD_INIT(name) PyMODINIT_FUNC PyInit_##name(void)
#define MOD_DEF(ob, name, doc, methods) \
static struct PyModuleDef moduledef = { \
PyModuleDef_HEAD_INIT, name, doc, -1, methods, }; \
ob = PyModule_Create(&moduledef);
#else
#define MOD_ERROR_VAL
#define MOD_SUCCESS_VAL(val)
#define MOD_INIT(name) PyMODINIT_FUNC init##name(void)
#define MOD_DEF(ob, name, doc, methods) \
ob = Py_InitModule3(name, methods, doc);
#endif
#include <time.h>
#ifdef __APPLE__ // OSX-only
#include "osxGetTime.h"
#endif
static double *times = NULL;
static int num_elements = 0;
static int num_allocated = 0;
int addToArray(double item) {
if (num_elements >= num_allocated) {
if (num_allocated == 0) {
num_allocated = 20;
} else {
num_allocated = num_allocated + 20;
}
void *_tmp = realloc(times, (num_allocated * sizeof(double)));
if (!_tmp) {
fprintf(stderr, "ERROR: Couldn't realloc memory!\n");
return(-1);
}
times = (double*)_tmp;
}
times[num_elements] = (double)item;
num_elements++;
return num_elements - 1;
}
double convertTsToDouble(struct timespec thetime) {
return ((double)thetime.tv_nsec / (double)1000000000) + (double)thetime.tv_sec;
}
double diff(double start, double end) {
double tmp = end - start;
if (tmp < 0) {
tmp = tmp * -1;
}
return (double)tmp;
}
struct timespec gettime(void) {
struct timespec temp;
#ifdef CLOCK_MONOTONIC_RAW
clock_gettime(CLOCK_MONOTONIC_RAW, &temp);
#elif CLOCK_MONOTONIC
clock_gettime(CLOCK_MONOTONIC, &temp);
#elif CLOCK_REALTIME
clock_gettime(CLOCK_REALTIME, &temp);
#endif
return temp;
}
static PyObject *
timer_start(PyObject *self, PyObject *args)
{
return Py_BuildValue("i", addToArray(convertTsToDouble(gettime())));
};
static PyObject *
timer_checkpoint(PyObject *self, PyObject *args)
{
return Py_BuildValue("i", addToArray(convertTsToDouble(gettime())));
};
static PyObject *
timer_stop(PyObject *self, PyObject *args)
{
return Py_BuildValue("i", addToArray(convertTsToDouble(gettime())));
};
static PyObject *
timer_diff(PyObject *self, PyObject *args)
{
int time1;
int time2;
if (!PyArg_ParseTuple(args, "ii", &time1, &time2)) {
return NULL;
}
if (time1 >= num_elements || time2 >= num_elements || time1 < 0 || time2 < 0) {
PyErr_SetString(PyExc_IndexError, "Invalid timer ID.");
return NULL;
}
return Py_BuildValue("d", (double)diff(times[time1], times[time2]));
};
static PyObject *
timer_get(PyObject *self, PyObject *args)
{
return Py_BuildValue("d", diff(times[0], convertTsToDouble(gettime())));
};
static PyMethodDef TimerMethods[] = {
{"get", timer_get, METH_NOARGS, "Get a relative timestamp as a float."},
{"start", timer_start, METH_NOARGS, "Get timer ID for a start point."},
{"checkpoint", timer_checkpoint, METH_NOARGS, "Get timer ID for a checkpoint."},
{"stop", timer_stop, METH_NOARGS, "Get timer ID for a stop point."},
{"diff", timer_diff, METH_VARARGS, "Get the difference in seconds between two checkpoint IDs as a double."},
{NULL, NULL, 0, NULL} /* Sentinel */
};
MOD_INIT(cTimer)
{
addToArray(convertTsToDouble(gettime()));
PyObject *m;
MOD_DEF(m, "cTimer", "A high precision timer.",
TimerMethods)
if (m == NULL)
return MOD_ERROR_VAL;
return MOD_SUCCESS_VAL(m);
//(void) Py_InitModule3("cTimer", TimerMethods, "A high precision timer.");
}