src/timeout.c

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
}