aboutsummaryrefslogtreecommitdiffstats
path: root/net/cqueues.lua
diff options
context:
space:
mode:
Diffstat (limited to 'net/cqueues.lua')
-rw-r--r--net/cqueues.lua56
1 files changed, 13 insertions, 43 deletions
diff --git a/net/cqueues.lua b/net/cqueues.lua
index 8c4c756f..65d2a019 100644
--- a/net/cqueues.lua
+++ b/net/cqueues.lua
@@ -9,6 +9,7 @@
local server = require "net.server";
local cqueues = require "cqueues";
+local timer = require "util.timer";
assert(cqueues.VERSION >= 20150113, "cqueues newer than 20150113 required")
-- Create a single top level cqueue
@@ -16,55 +17,24 @@ local cq;
if server.cq then -- server provides cqueues object
cq = server.cq;
-elseif server.get_backend() == "select" and server._addtimer then -- server_select
+elseif server.watchfd then
cq = cqueues.new();
- local function step()
+ local timeout = timer.add_task(cq:timeout() or 0, function ()
+ -- FIXME It should be enough to reschedule this timeout instead of replacing it, but this does not work. See https://issues.prosody.im/1572
assert(cq:loop(0));
- end
-
- -- Use wrapclient (as wrapconnection isn't exported) to get server_select to watch cq fd
- local handler = server.wrapclient({
- getfd = function() return cq:pollfd(); end;
- settimeout = function() end; -- Method just needs to exist
- close = function() end; -- Need close method for 'closeall'
- }, nil, nil, {});
-
- -- Only need to listen for readable; cqueues handles everything under the hood
- -- readbuffer is called when `select` notes an fd as readable
- handler.readbuffer = step;
-
- -- Use server_select low lever timer facility,
- -- this callback gets called *every* time there is a timeout in the main loop
- server._addtimer(function(current_time)
- -- This may end up in extra step()'s, but cqueues handles it for us.
- step();
return cq:timeout();
end);
-elseif server.event and server.base then -- server_event
- cq = cqueues.new();
- -- Only need to listen for readable; cqueues handles everything under the hood
- local EV_READ = server.event.EV_READ;
- -- Convert a cqueues timeout to an acceptable timeout for luaevent
- local function luaevent_safe_timeout(cq)
+ server.watchfd(cq:pollfd(), function ()
+ assert(cq:loop(0));
local t = cq:timeout();
- -- if you give luaevent 0 or nil, it re-uses the previous timeout.
- if t == 0 then
- t = 0.000001; -- 1 microsecond is the smallest that works (goes into a `struct timeval`)
- elseif t == nil then -- pick something big if we don't have one
- t = 0x7FFFFFFF; -- largest 32bit int
+ if t then
+ timer.stop(timeout);
+ timeout = timer.add_task(cq:timeout(), function ()
+ assert(cq:loop(0));
+ return cq:timeout();
+ end);
end
- return t
- end
- local event_handle;
- event_handle = server.base:addevent(cq:pollfd(), EV_READ, function(e)
- -- Need to reference event_handle or this callback will get collected
- -- This creates a circular reference that can only be broken if event_handle is manually :close()'d
- local _ = event_handle;
- -- Run as many cqueues things as possible (with a timeout of 0)
- -- If an error is thrown, it will break the libevent loop; but prosody resumes after logging a top level error
- assert(cq:loop(0));
- return EV_READ, luaevent_safe_timeout(cq);
- end, luaevent_safe_timeout(cq));
+ end);
else
error "NYI"
end