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 {