Ne.app NeANT
The Ne.app NeANT User module of the NeANT distribution.
alarm.cpp
Go to the documentation of this file.
1
29// expand _TEST_EXPORT macros
30#define _RWSTD_TEST_SRC
31
32// including <time.h> first works around a SunPro/SunOS bug (PR #26255)
33#include <time.h> // for time_t
34
35#include <assert.h> // for assert()
36#include <stdio.h> // for sprintf()
37
38#include <rw_alarm.h> // for rw_alarm()
39#include <rw_printf.h> // for rw_fprintf()
40
41
42// avoid re-declaring the constants below extern exported to prevent
43// MSVC error: object must have external linkage in order to be
44// exported/imported
45
46/* extern _TEST_EXPORT */ rw_signal_handler_t* const
48
49/* extern _TEST_EXPORT */ rw_signal_handler_t* const
51
52/* extern _TEST_EXPORT */ rw_signal_handler_t* const
54
55/* extern _TEST_EXPORT */ rw_signal_handler_t* const
57
58
59// may point to a user-defined handler for the alarm
61_rw_alarm_handler;
62
63
64#ifdef _WIN32
65
66#include <windows.h>
67
68// CygWin doesn't seem to define alarm()...
69
70// thread procedure
71static DWORD WINAPI
72_rw_alarm_proc (LPVOID arg /* seconds */)
73{
74 Sleep (1000U * (ULONG)arg);
75
76 rw_fprintf (rw_stderr, "%s:%d alarm expired\n", __FILE__, __LINE__);
77
78 if (_rw_alarm_handler)
79 _rw_alarm_handler (0);
80 else
81 abort (); // no SIGALRM on Win32
82
83 return 0;
84}
85
86
87// rough equivalent of POSIX alarm
89unsigned int
90rw_alarm (unsigned int nsec, rw_signal_handler_t* handler /* = 0 */)
91{
92 static HANDLE thread = 0; // thread handle (one alarm per process)
93 static unsigned pending = 0; // previous alarm() argument
94 static time_t t0 = 0; // start of previous alarm()
95 time_t unslept = 0; // seconds until previous alarm expires
96
97 if (thread) {
98 // previous alarm is still pending, cancel it
99 unslept = pending - (time (0) - t0);
100 TerminateThread (thread, 0);
101 CloseHandle (thread);
102 thread = 0;
103 }
104
105 pending = nsec;
106
107 if (nsec) {
108 time (&t0); // keep track of when countdown started
109
110 if (handler) {
111 // take care not to overwrite any previously set handler
112 _rw_alarm_handler = handler;
113 }
114
115 DWORD tid; // dummy (not used, required on Win95)
116 thread = CreateThread (0, 0, _rw_alarm_proc, (LPVOID)nsec, 0, &tid);
117 // thread handle will leak unless alarm (0) is called
118 }
119
120 return unsigned (unslept);
121}
122
123
124#else // ifndef _WIN32
125
126# include <signal.h> // for SIGALRM, signal()
127# include <unistd.h> // for alarm(), write()
128
129 // define macros in case they aren't #defined by
130 // the system headers e.g., when using pure libc headers
131# ifndef SIGALRM
132# define SIGALRM 14 /* e.g., Solaris */
133# endif
134
135# ifndef SIG_DFL
136# define SIG_DFL (rw_signal_handler_t*)0
137# endif // SIG_DFL
138
139# ifndef SIG_IGN
140# define SIG_IGN (rw_signal_handler_t*)1
141# endif // SIG_IGN
142
143# ifndef SIG_HOLD
144# define SIG_HOLD (rw_signal_handler_t*)2
145# endif // SIG_HOLD
146
147
148extern "C" {
149
150static void
151_rw_handle_sigalrm (int signo)
152{
153 assert (SIGALRM == signo);
154
155 char buffer [1024];
156
157 // fprintf() is not async-signal safe...
158 const int len =
159 sprintf (buffer, "%s:%d: alarm expired\n", __FILE__, __LINE__);
160
161 // ...use write() instead
162 write (STDERR_FILENO, buffer, size_t (len));
163
164 if (_rw_alarm_handler)
165 _rw_alarm_handler (signo);
166}
167
168} // extern "C"
169
170
172unsigned
173rw_alarm (unsigned int nsec, rw_signal_handler_t* handler /* = 0 */)
174{
175 static rw_signal_handler_t* saved_handler = 0;
176 static unsigned saved_nsec = 0;
177
178 if (rw_sig_hold == handler) {
179 // hold and save the current SIGALRM handler
180 // and just retrieve the current alarm
181 saved_handler = signal (SIGALRM, (rw_signal_handler_t*)SIG_HOLD);
182 saved_nsec = alarm (0);
183
184 alarm (saved_nsec);
185
186 return saved_nsec;
187 }
188
189 if (rw_sig_restore == handler) {
190 // restore the previously saved SIGALRM handler
191 // and set a new alarm to go off approximately
192 // after (saved_nsec - nsec) seconds
193
194 if (saved_handler) {
195 signal (SIGALRM, saved_handler);
196
197 if (nsec < saved_nsec)
198 nsec = saved_nsec - nsec;
199 else
200 nsec = 1;
201
202 alarm (nsec);
203
204 // return the new timeout
205 return nsec;
206 }
207
208 // return 0 to indicate that no alarm was set
209 return 0;
210 }
211
212 if (rw_sig_dfl == handler) {
214 }
215 else if (rw_sig_ign == handler) {
217 }
218 else if (handler) {
219 // take care not to overwrite any previously set handler
220 _rw_alarm_handler = handler;
221 signal (SIGALRM, _rw_handle_sigalrm);
222 }
223
224 return alarm (nsec);
225}
226
227
228#endif // _WIN32
#define ULONG
Definition 17.names.cpp:566
#define pending
Definition 17.names.cpp:524
#define buffer
Definition 17.names.cpp:453
#define len
Definition 17.names.cpp:488
void handler()
#define STDERR_FILENO
#define assert(expr)
Definition _cassert.h:40
#define SIG_HOLD
Definition alarm.cpp:144
#define SIG_DFL
Definition alarm.cpp:136
rw_signal_handler_t *const rw_sig_restore
Definition alarm.cpp:56
rw_signal_handler_t *const rw_sig_dfl
Definition alarm.cpp:47
rw_signal_handler_t *const rw_sig_hold
Definition alarm.cpp:53
#define SIGALRM
Definition alarm.cpp:132
#define SIG_IGN
Definition alarm.cpp:140
_TEST_EXPORT unsigned rw_alarm(unsigned int nsec, rw_signal_handler_t *handler)
Definition alarm.cpp:173
rw_signal_handler_t *const rw_sig_ign
Definition alarm.cpp:50
void rw_signal_handler_t(int)
Definition rw_alarm.h:38
_TEST_EXPORT rw_file *const rw_stderr
Definition printf.cpp:3348
_TEST_EXPORT int rw_fprintf(rw_file *, const char *,...)
Definition printf.cpp:3397
#define _TEST_EXPORT
Definition rw_testdefs.h:55
A local time-of-day.
int arg
Definition locale.cpp:2806