Software /
code /
prosody
Comparison
net/cqueues.lua @ 10996:d742095046f9
net.cqueues: Switch to server.watchfd for main loop integration
Why? Just look at all that code deleted!
watchfd is the prefered way to poll things that expose FDs for this
purpose, altho it was added after net.cqueues.
author | Kim Alvefur <zash@zash.se> |
---|---|
date | Wed, 08 Jul 2020 20:11:49 +0200 |
parent | 6538:f1eb66288f60 |
child | 10999:37b884d675f7 |
comparison
equal
deleted
inserted
replaced
10995:e18a913aed2d | 10996:d742095046f9 |
---|---|
14 -- Create a single top level cqueue | 14 -- Create a single top level cqueue |
15 local cq; | 15 local cq; |
16 | 16 |
17 if server.cq then -- server provides cqueues object | 17 if server.cq then -- server provides cqueues object |
18 cq = server.cq; | 18 cq = server.cq; |
19 elseif server.get_backend() == "select" and server._addtimer then -- server_select | 19 elseif server.watchfd then |
20 cq = cqueues.new(); | 20 cq = cqueues.new(); |
21 local function step() | 21 server.watchfd(cq:pollfd(), function () |
22 assert(cq:loop(0)); | 22 assert(cq:loop(0)); |
23 end | |
24 | |
25 -- Use wrapclient (as wrapconnection isn't exported) to get server_select to watch cq fd | |
26 local handler = server.wrapclient({ | |
27 getfd = function() return cq:pollfd(); end; | |
28 settimeout = function() end; -- Method just needs to exist | |
29 close = function() end; -- Need close method for 'closeall' | |
30 }, nil, nil, {}); | |
31 | |
32 -- Only need to listen for readable; cqueues handles everything under the hood | |
33 -- readbuffer is called when `select` notes an fd as readable | |
34 handler.readbuffer = step; | |
35 | |
36 -- Use server_select low lever timer facility, | |
37 -- this callback gets called *every* time there is a timeout in the main loop | |
38 server._addtimer(function(current_time) | |
39 -- This may end up in extra step()'s, but cqueues handles it for us. | |
40 step(); | |
41 return cq:timeout(); | |
42 end); | 23 end); |
43 elseif server.event and server.base then -- server_event | |
44 cq = cqueues.new(); | |
45 -- Only need to listen for readable; cqueues handles everything under the hood | |
46 local EV_READ = server.event.EV_READ; | |
47 -- Convert a cqueues timeout to an acceptable timeout for luaevent | |
48 local function luaevent_safe_timeout(cq) | |
49 local t = cq:timeout(); | |
50 -- if you give luaevent 0 or nil, it re-uses the previous timeout. | |
51 if t == 0 then | |
52 t = 0.000001; -- 1 microsecond is the smallest that works (goes into a `struct timeval`) | |
53 elseif t == nil then -- pick something big if we don't have one | |
54 t = 0x7FFFFFFF; -- largest 32bit int | |
55 end | |
56 return t | |
57 end | |
58 local event_handle; | |
59 event_handle = server.base:addevent(cq:pollfd(), EV_READ, function(e) | |
60 -- Need to reference event_handle or this callback will get collected | |
61 -- This creates a circular reference that can only be broken if event_handle is manually :close()'d | |
62 local _ = event_handle; | |
63 -- Run as many cqueues things as possible (with a timeout of 0) | |
64 -- If an error is thrown, it will break the libevent loop; but prosody resumes after logging a top level error | |
65 assert(cq:loop(0)); | |
66 return EV_READ, luaevent_safe_timeout(cq); | |
67 end, luaevent_safe_timeout(cq)); | |
68 else | 24 else |
69 error "NYI" | 25 error "NYI" |
70 end | 26 end |
71 | 27 |
72 return { | 28 return { |