Software /
code /
prosody
Comparison
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 |
comparison
equal
deleted
inserted
replaced
6513:3bbd59c03aeb | 6514:d425fc41e59f |
---|---|
1 -- Prosody IM | |
2 -- Copyright (C) 2014 Daurnimator | |
3 -- | |
4 -- This project is MIT/X11 licensed. Please see the | |
5 -- COPYING file in the source package for more information. | |
6 -- | |
7 -- This module allows you to use cqueues with a net.server mainloop | |
8 -- | |
9 | |
10 local server = require "net.server"; | |
11 local cqueues = require "cqueues"; | |
12 | |
13 -- Create a single top level cqueue | |
14 local cq; | |
15 | |
16 if server.cq then -- server provides cqueues object | |
17 cq = server.cq; | |
18 elseif server.get_backend() == "select" and server._addtimer then -- server_select | |
19 cq = cqueues.new(); | |
20 local function step() | |
21 assert(cq:loop(0)); | |
22 end | |
23 | |
24 -- Use wrapclient (as wrapconnection isn't exported) to get server_select to watch cq fd | |
25 local handler = server.wrapclient({ | |
26 getfd = function() return cq:pollfd(); end; | |
27 settimeout = function() end; -- Method just needs to exist | |
28 close = function() end; -- Need close method for 'closeall' | |
29 }, nil, nil, {}); | |
30 | |
31 -- Only need to listen for readable; cqueues handles everything under the hood | |
32 -- readbuffer is called when `select` notes an fd as readable | |
33 handler.readbuffer = step; | |
34 | |
35 -- Use server_select low lever timer facility, | |
36 -- this callback gets called *every* time there is a timeout in the main loop | |
37 server._addtimer(function(current_time) | |
38 -- This may end up in extra step()'s, but cqueues handles it for us. | |
39 step(); | |
40 return cq:timeout(); | |
41 end); | |
42 elseif server.event and server.base then -- server_event | |
43 cq = cqueues.new(); | |
44 -- Only need to listen for readable; cqueues handles everything under the hood | |
45 local EV_READ = server.event.EV_READ; | |
46 server.base:addevent(cq:pollfd(), EV_READ, function(e) | |
47 assert(cq:loop(0)); | |
48 -- Convert a cq timeout to an acceptable timeout for luaevent | |
49 local t = cq:timeout(); | |
50 if t == 0 then -- if you give luaevent 0, it won't call this callback again | |
51 t = 0.000001; -- 1 microsecond is the smallest that works (goes into a `struct timeval`) | |
52 elseif t == nil then -- you always need to give a timeout, pick something big if we don't have one | |
53 t = 0x7FFFFFFF; -- largest 32bit int | |
54 end | |
55 return EV_READ, t; | |
56 end, | |
57 -- Schedule the callback to fire on first tick to ensure any cq:wrap calls that happen during start-up are serviced. | |
58 0.000001); | |
59 else | |
60 error "NYI" | |
61 end | |
62 | |
63 return { | |
64 cq = cq; | |
65 } |