88
88
89
89
// init fills the `file_descriptors` array
90
90
pub fn (mut pv Picoev) init () {
91
- assert max_fds > 0
92
-
91
+ // assert max_fds > 0
93
92
pv.num_loops = 0
94
-
95
93
for i in 0 .. max_fds {
96
94
pv.file_descriptors[i] = & Target{}
97
95
}
@@ -103,21 +101,17 @@ pub fn (mut pv Picoev) add(fd int, events int, timeout int, callback voidptr) in
103
101
if pv == unsafe { nil } || fd < 0 || fd > = max_fds {
104
102
return - 1 // Invalid arguments
105
103
}
106
-
107
104
mut target := pv.file_descriptors[fd]
108
105
target.fd = fd
109
106
target.cb = callback
110
107
target.loop_id = pv.loop.id
111
108
target.events = 0
112
-
113
109
if pv.update_events (fd, events | picoev_add) != 0 {
114
110
if pv.delete (fd) != 0 {
115
111
elog ('Error during del' )
116
112
}
117
-
118
113
return - 1
119
114
}
120
-
121
115
pv.set_timeout (fd, timeout)
122
116
return 0
123
117
}
@@ -135,18 +129,12 @@ pub fn (mut pv Picoev) delete(fd int) int {
135
129
if fd < 0 || fd > = max_fds {
136
130
return - 1 // Invalid fd
137
131
}
138
-
139
132
mut target := pv.file_descriptors[fd]
140
-
141
- $if trace_fd ? {
142
- eprintln ('remove ${fd} ' )
143
- }
144
-
133
+ trace_fd ('remove ${fd} ' )
145
134
if pv.update_events (fd, picoev_del) != 0 {
146
135
elog ('Error during update_events. event: `picoev.picoev_del`' )
147
136
return - 1
148
137
}
149
-
150
138
pv.set_timeout (fd, 0 )
151
139
target.loop_id = - 1
152
140
target.fd = 0
@@ -156,19 +144,16 @@ pub fn (mut pv Picoev) delete(fd int) int {
156
144
157
145
fn (mut pv Picoev) loop_once (max_wait_in_sec int ) int {
158
146
pv.loop.now = get_time ()
159
-
160
147
if pv.poll_once (max_wait_in_sec) != 0 {
161
148
elog ('Error during poll_once' )
162
149
return - 1
163
150
}
164
-
165
- if max_wait_in_sec != 0 {
166
- pv.loop.now = get_time () // Update loop start time again if waiting occurred
167
- } else {
151
+ if max_wait_in_sec == 0 {
168
152
// If no waiting, skip timeout handling for potential performance optimization
169
153
return 0
170
154
}
171
-
155
+ // Update loop start time again if waiting occurred
156
+ pv.loop.now = get_time ()
172
157
pv.handle_timeout ()
173
158
return 0
174
159
}
@@ -178,10 +163,10 @@ fn (mut pv Picoev) loop_once(max_wait_in_sec int) int {
178
163
@[direct_array_access; inline]
179
164
fn (mut pv Picoev) set_timeout (fd int , secs int ) {
180
165
assert fd < max_fds
181
- if secs != 0 {
182
- pv.timeouts[fd] = pv.loop.now + secs
183
- } else {
166
+ if secs == 0 {
184
167
pv.timeouts.delete (fd)
168
+ } else {
169
+ pv.timeouts[fd] = pv.loop.now + secs
185
170
}
186
171
}
187
172
@@ -191,13 +176,11 @@ fn (mut pv Picoev) set_timeout(fd int, secs int) {
191
176
@[direct_array_access; inline]
192
177
fn (mut pv Picoev) handle_timeout () {
193
178
mut to_remove := []int {}
194
-
195
179
for fd, timeout in pv.timeouts {
196
180
if timeout < = pv.loop.now {
197
181
to_remove << fd
198
182
}
199
183
}
200
-
201
184
for fd in to_remove {
202
185
target := pv.file_descriptors[fd]
203
186
assert target.loop_id == pv.loop.id
@@ -210,26 +193,19 @@ fn (mut pv Picoev) handle_timeout() {
210
193
fn accept_callback (listen_fd int , events int , cb_arg voidptr ) {
211
194
mut pv := unsafe { & Picoev (cb_arg) }
212
195
accepted_fd := accept (listen_fd)
213
-
214
196
if accepted_fd == - 1 {
215
197
if fatal_socket_error (accepted_fd) == false {
216
198
return
217
199
}
218
-
219
200
elog ('Error during accept' )
220
201
return
221
202
}
222
-
223
203
if accepted_fd > = max_fds {
224
204
// should never happen
225
205
close_socket (accepted_fd)
226
206
return
227
207
}
228
-
229
- $if trace_fd ? {
230
- eprintln ('accept ${accepted_fd} ' )
231
- }
232
-
208
+ trace_fd ('accept ${accepted_fd} ' )
233
209
setup_sock (accepted_fd) or {
234
210
elog ('setup_sock failed, fd: ${accepted_fd} , listen_fd: ${listen_fd} , err: ${err.code()} ' )
235
211
pv.error_callback (pv.user_data, picohttpparser.Request{}, mut & picohttpparser.Response{},
@@ -256,17 +232,12 @@ fn raw_callback(fd int, events int, context voidptr) {
256
232
defer {
257
233
pv.idx[fd] = 0
258
234
}
259
-
260
235
if events & picoev_timeout != 0 {
261
- $if trace_fd ? {
262
- eprintln ('timeout ${fd} ' )
263
- }
264
-
236
+ trace_fd ('timeout ${fd} ' )
265
237
if ! isnil (pv.raw_callback) {
266
238
pv.raw_callback (mut pv, fd, events)
267
239
return
268
240
}
269
-
270
241
pv.close_conn (fd)
271
242
return
272
243
} else if events & picoev_read != 0 {
@@ -275,13 +246,11 @@ fn raw_callback(fd int, events int, context voidptr) {
275
246
pv.raw_callback (mut pv, fd, events)
276
247
return
277
248
}
278
-
279
249
mut request_buffer := pv.buf
280
250
unsafe {
281
251
request_buffer + = fd * pv.max_read // pointer magic
282
252
}
283
253
mut req := picohttpparser.Request{}
284
-
285
254
// Response init
286
255
mut response_buffer := pv.out
287
256
unsafe {
@@ -293,7 +262,6 @@ fn raw_callback(fd int, events int, context voidptr) {
293
262
buf: response_buffer
294
263
date: pv.date.str
295
264
}
296
-
297
265
for {
298
266
// Request parsing loop
299
267
r := req_read (fd, request_buffer, pv.max_read, pv.idx[fd]) // Get data from socket
@@ -305,15 +273,12 @@ fn raw_callback(fd int, events int, context voidptr) {
305
273
if fatal_socket_error (fd) == false {
306
274
return
307
275
}
308
-
309
276
elog ('Error during req_read' )
310
-
311
277
// fatal error
312
278
pv.close_conn (fd)
313
279
return
314
280
}
315
281
pv.idx[fd] + = r
316
-
317
282
mut s := unsafe { tos (request_buffer, pv.idx[fd]) }
318
283
pret := req.parse_request (s) or {
319
284
// Parse error
@@ -323,15 +288,13 @@ fn raw_callback(fd int, events int, context voidptr) {
323
288
if pret > 0 { // Success
324
289
break
325
290
}
326
-
327
291
assert pret == - 2
328
292
// request is incomplete, continue the loop
329
293
if pv.idx[fd] == sizeof (request_buffer) {
330
294
pv.error_callback (pv.user_data, req, mut & res, error ('RequestIsTooLongError' ))
331
295
return
332
296
}
333
297
}
334
-
335
298
// Callback (should call .end() itself)
336
299
pv.cb (pv.user_data, req, mut & res)
337
300
} else if events & picoev_write != 0 {
@@ -354,7 +317,6 @@ pub fn new(config Config) !&Picoev {
354
317
elog ('Error during listen: ${err} ' )
355
318
return err
356
319
}
357
-
358
320
mut pv := & Picoev{
359
321
num_loops: 1
360
322
cb: config.cb
@@ -366,12 +328,10 @@ pub fn new(config Config) !&Picoev {
366
328
max_read: config.max_read
367
329
max_write: config.max_write
368
330
}
369
-
370
331
if isnil (pv.raw_callback) {
371
332
pv.buf = unsafe { malloc_noscan (max_fds * config.max_read + 1 ) }
372
333
pv.out = unsafe { malloc_noscan (max_fds * config.max_write + 1 ) }
373
334
}
374
-
375
335
// epoll on linux
376
336
// kqueue on macos and bsd
377
337
// select on windows and others
@@ -382,15 +342,12 @@ pub fn new(config Config) !&Picoev {
382
342
} $else {
383
343
pv.loop = create_select_loop (0 ) or { panic (err) }
384
344
}
385
-
386
345
if pv.loop == unsafe { nil } {
387
346
elog ('Failed to create loop' )
388
347
close_socket (listening_socket_fd)
389
348
return unsafe { nil }
390
349
}
391
-
392
350
pv.init ()
393
-
394
351
pv.add (listening_socket_fd, picoev_read, 0 , accept_callback)
395
352
return pv
396
353
}
@@ -399,7 +356,6 @@ pub fn new(config Config) !&Picoev {
399
356
// See also picoev.new().
400
357
pub fn (mut pv Picoev) serve () {
401
358
spawn update_date_string (mut pv)
402
-
403
359
for {
404
360
pv.loop_once (1 )
405
361
}
0 commit comments