|
1 /*=========================================================================*\ |
|
2 * LuaSocket 2.0.2 |
|
3 * Copyright (C) 2004-2007 Diego Nehab |
|
4 * |
|
5 * Timeout management functions |
|
6 * |
|
7 * RCS ID: $Id: timeout.c,v 1.30 2005/10/07 04:40:59 diego Exp $ |
|
8 \*=========================================================================*/ |
|
9 #include <stdio.h> |
|
10 |
|
11 #ifdef _WIN32 |
|
12 #include <windows.h> |
|
13 #else |
|
14 #include <time.h> |
|
15 #include <sys/time.h> |
|
16 #endif |
|
17 |
|
18 #include <lua.h> |
|
19 #include <lauxlib.h> |
|
20 |
|
21 #include "timeout.h" |
|
22 |
|
23 /* min and max macros */ |
|
24 #ifndef MIN |
|
25 #define MIN(x, y) ((x) < (y) ? x : y) |
|
26 #endif |
|
27 #ifndef MAX |
|
28 #define MAX(x, y) ((x) > (y) ? x : y) |
|
29 #endif |
|
30 |
|
31 /*=========================================================================*\ |
|
32 * Exported functions. |
|
33 \*=========================================================================*/ |
|
34 /*-------------------------------------------------------------------------*\ |
|
35 * Initialize structure |
|
36 \*-------------------------------------------------------------------------*/ |
|
37 void timeout_init(p_timeout tm, double block, double total) { |
|
38 tm->block = block; |
|
39 tm->total = total; |
|
40 } |
|
41 |
|
42 /*-------------------------------------------------------------------------*\ |
|
43 * Determines how much time we have left for the next system call, |
|
44 * if the previous call was successful |
|
45 * Input |
|
46 * tm: timeout control structure |
|
47 * Returns |
|
48 * the number of ms left or -1 if there is no time limit |
|
49 \*-------------------------------------------------------------------------*/ |
|
50 double timeout_get(p_timeout tm) { |
|
51 if (tm->block < 0.0 && tm->total < 0.0) { |
|
52 return -1; |
|
53 } else if (tm->block < 0.0) { |
|
54 double t = tm->total - timeout_gettime() + tm->start; |
|
55 return MAX(t, 0.0); |
|
56 } else if (tm->total < 0.0) { |
|
57 return tm->block; |
|
58 } else { |
|
59 double t = tm->total - timeout_gettime() + tm->start; |
|
60 return MIN(tm->block, MAX(t, 0.0)); |
|
61 } |
|
62 } |
|
63 |
|
64 /*-------------------------------------------------------------------------*\ |
|
65 * Returns time since start of operation |
|
66 * Input |
|
67 * tm: timeout control structure |
|
68 * Returns |
|
69 * start field of structure |
|
70 \*-------------------------------------------------------------------------*/ |
|
71 double timeout_getstart(p_timeout tm) { |
|
72 return tm->start; |
|
73 } |
|
74 |
|
75 /*-------------------------------------------------------------------------*\ |
|
76 * Determines how much time we have left for the next system call, |
|
77 * if the previous call was a failure |
|
78 * Input |
|
79 * tm: timeout control structure |
|
80 * Returns |
|
81 * the number of ms left or -1 if there is no time limit |
|
82 \*-------------------------------------------------------------------------*/ |
|
83 double timeout_getretry(p_timeout tm) { |
|
84 if (tm->block < 0.0 && tm->total < 0.0) { |
|
85 return -1; |
|
86 } else if (tm->block < 0.0) { |
|
87 double t = tm->total - timeout_gettime() + tm->start; |
|
88 return MAX(t, 0.0); |
|
89 } else if (tm->total < 0.0) { |
|
90 double t = tm->block - timeout_gettime() + tm->start; |
|
91 return MAX(t, 0.0); |
|
92 } else { |
|
93 double t = tm->total - timeout_gettime() + tm->start; |
|
94 return MIN(tm->block, MAX(t, 0.0)); |
|
95 } |
|
96 } |
|
97 |
|
98 /*-------------------------------------------------------------------------*\ |
|
99 * Marks the operation start time in structure |
|
100 * Input |
|
101 * tm: timeout control structure |
|
102 \*-------------------------------------------------------------------------*/ |
|
103 p_timeout timeout_markstart(p_timeout tm) { |
|
104 tm->start = timeout_gettime(); |
|
105 return tm; |
|
106 } |
|
107 |
|
108 /*-------------------------------------------------------------------------*\ |
|
109 * Gets time in s, relative to January 1, 1970 (UTC) |
|
110 * Returns |
|
111 * time in s. |
|
112 \*-------------------------------------------------------------------------*/ |
|
113 #ifdef _WIN32 |
|
114 double timeout_gettime(void) { |
|
115 FILETIME ft; |
|
116 double t; |
|
117 GetSystemTimeAsFileTime(&ft); |
|
118 /* Windows file time (time since January 1, 1601 (UTC)) */ |
|
119 t = ft.dwLowDateTime/1.0e7 + ft.dwHighDateTime*(4294967296.0/1.0e7); |
|
120 /* convert to Unix Epoch time (time since January 1, 1970 (UTC)) */ |
|
121 return (t - 11644473600.0); |
|
122 } |
|
123 #else |
|
124 double timeout_gettime(void) { |
|
125 struct timeval v; |
|
126 gettimeofday(&v, (struct timezone *) NULL); |
|
127 /* Unix Epoch time (time since January 1, 1970 (UTC)) */ |
|
128 return v.tv_sec + v.tv_usec/1.0e6; |
|
129 } |
|
130 #endif |
|
131 |
|
132 /*-------------------------------------------------------------------------*\ |
|
133 * Sets timeout values for IO operations |
|
134 * Lua Input: base, time [, mode] |
|
135 * time: time out value in seconds |
|
136 * mode: "b" for block timeout, "t" for total timeout. (default: b) |
|
137 \*-------------------------------------------------------------------------*/ |
|
138 int timeout_meth_settimeout(lua_State *L, p_timeout tm) { |
|
139 double t = luaL_optnumber(L, 2, -1); |
|
140 const char *mode = luaL_optstring(L, 3, "b"); |
|
141 switch (*mode) { |
|
142 case 'b': |
|
143 tm->block = t; |
|
144 break; |
|
145 case 'r': case 't': |
|
146 tm->total = t; |
|
147 break; |
|
148 default: |
|
149 luaL_argcheck(L, 0, 3, "invalid timeout mode"); |
|
150 break; |
|
151 } |
|
152 lua_pushnumber(L, 1); |
|
153 return 1; |
|
154 } |
|
155 |