Software /
code /
prosody
File
net/cqueues.lua @ 6514:d425fc41e59f
net.cqueues: Add module that allows use of cqueues while still using net.server as main loop
author | daurnimator <quae@daurnimator.com> |
---|---|
date | Tue, 18 Nov 2014 14:14:41 -0500 |
child | 6536:605a87e90e27 |
line wrap: on
line source
-- Prosody IM -- Copyright (C) 2014 Daurnimator -- -- This project is MIT/X11 licensed. Please see the -- COPYING file in the source package for more information. -- -- This module allows you to use cqueues with a net.server mainloop -- local server = require "net.server"; local cqueues = require "cqueues"; -- Create a single top level cqueue local cq; if server.cq then -- server provides cqueues object cq = server.cq; elseif server.get_backend() == "select" and server._addtimer then -- server_select cq = cqueues.new(); local function step() 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; server.base:addevent(cq:pollfd(), EV_READ, function(e) assert(cq:loop(0)); -- Convert a cq timeout to an acceptable timeout for luaevent local t = cq:timeout(); if t == 0 then -- if you give luaevent 0, it won't call this callback again t = 0.000001; -- 1 microsecond is the smallest that works (goes into a `struct timeval`) elseif t == nil then -- you always need to give a timeout, pick something big if we don't have one t = 0x7FFFFFFF; -- largest 32bit int end return EV_READ, t; end, -- Schedule the callback to fire on first tick to ensure any cq:wrap calls that happen during start-up are serviced. 0.000001); else error "NYI" end return { cq = cq; }