net/cqueues.lua
author Kim Alvefur <zash@zash.se>
Thu, 04 Nov 2021 01:00:06 +0100
branch0.11
changeset 12093 76b4e3f12b53
parent 6541 f1eb66288f60
child 11000 d742095046f9
permissions -rw-r--r--
mod_pep: Wipe pubsub service on user deletion Data is already wiped from storage, but this ensures everything is properly unsubscribed, possibly with notifications etc. Clears recipient cache as well, since it is no longer relevant.
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
6517
d425fc41e59f net.cqueues: Add module that allows use of cqueues while still using net.server as main loop
daurnimator <quae@daurnimator.com>
parents:
diff changeset
     1
-- Prosody IM
d425fc41e59f net.cqueues: Add module that allows use of cqueues while still using net.server as main loop
daurnimator <quae@daurnimator.com>
parents:
diff changeset
     2
-- Copyright (C) 2014 Daurnimator
d425fc41e59f net.cqueues: Add module that allows use of cqueues while still using net.server as main loop
daurnimator <quae@daurnimator.com>
parents:
diff changeset
     3
--
d425fc41e59f net.cqueues: Add module that allows use of cqueues while still using net.server as main loop
daurnimator <quae@daurnimator.com>
parents:
diff changeset
     4
-- This project is MIT/X11 licensed. Please see the
d425fc41e59f net.cqueues: Add module that allows use of cqueues while still using net.server as main loop
daurnimator <quae@daurnimator.com>
parents:
diff changeset
     5
-- COPYING file in the source package for more information.
d425fc41e59f net.cqueues: Add module that allows use of cqueues while still using net.server as main loop
daurnimator <quae@daurnimator.com>
parents:
diff changeset
     6
--
d425fc41e59f net.cqueues: Add module that allows use of cqueues while still using net.server as main loop
daurnimator <quae@daurnimator.com>
parents:
diff changeset
     7
-- This module allows you to use cqueues with a net.server mainloop
d425fc41e59f net.cqueues: Add module that allows use of cqueues while still using net.server as main loop
daurnimator <quae@daurnimator.com>
parents:
diff changeset
     8
--
d425fc41e59f net.cqueues: Add module that allows use of cqueues while still using net.server as main loop
daurnimator <quae@daurnimator.com>
parents:
diff changeset
     9
d425fc41e59f net.cqueues: Add module that allows use of cqueues while still using net.server as main loop
daurnimator <quae@daurnimator.com>
parents:
diff changeset
    10
local server = require "net.server";
d425fc41e59f net.cqueues: Add module that allows use of cqueues while still using net.server as main loop
daurnimator <quae@daurnimator.com>
parents:
diff changeset
    11
local cqueues = require "cqueues";
6541
f1eb66288f60 net.cqueues: Fix incorrect version check
daurnimator <quae@daurnimator.com>
parents: 6540
diff changeset
    12
assert(cqueues.VERSION >= 20150113, "cqueues newer than 20150113 required")
6517
d425fc41e59f net.cqueues: Add module that allows use of cqueues while still using net.server as main loop
daurnimator <quae@daurnimator.com>
parents:
diff changeset
    13
d425fc41e59f net.cqueues: Add module that allows use of cqueues while still using net.server as main loop
daurnimator <quae@daurnimator.com>
parents:
diff changeset
    14
-- Create a single top level cqueue
d425fc41e59f net.cqueues: Add module that allows use of cqueues while still using net.server as main loop
daurnimator <quae@daurnimator.com>
parents:
diff changeset
    15
local cq;
d425fc41e59f net.cqueues: Add module that allows use of cqueues while still using net.server as main loop
daurnimator <quae@daurnimator.com>
parents:
diff changeset
    16
d425fc41e59f net.cqueues: Add module that allows use of cqueues while still using net.server as main loop
daurnimator <quae@daurnimator.com>
parents:
diff changeset
    17
if server.cq then -- server provides cqueues object
d425fc41e59f net.cqueues: Add module that allows use of cqueues while still using net.server as main loop
daurnimator <quae@daurnimator.com>
parents:
diff changeset
    18
	cq = server.cq;
d425fc41e59f net.cqueues: Add module that allows use of cqueues while still using net.server as main loop
daurnimator <quae@daurnimator.com>
parents:
diff changeset
    19
elseif server.get_backend() == "select" and server._addtimer then -- server_select
d425fc41e59f net.cqueues: Add module that allows use of cqueues while still using net.server as main loop
daurnimator <quae@daurnimator.com>
parents:
diff changeset
    20
	cq = cqueues.new();
d425fc41e59f net.cqueues: Add module that allows use of cqueues while still using net.server as main loop
daurnimator <quae@daurnimator.com>
parents:
diff changeset
    21
	local function step()
d425fc41e59f net.cqueues: Add module that allows use of cqueues while still using net.server as main loop
daurnimator <quae@daurnimator.com>
parents:
diff changeset
    22
		assert(cq:loop(0));
d425fc41e59f net.cqueues: Add module that allows use of cqueues while still using net.server as main loop
daurnimator <quae@daurnimator.com>
parents:
diff changeset
    23
	end
d425fc41e59f net.cqueues: Add module that allows use of cqueues while still using net.server as main loop
daurnimator <quae@daurnimator.com>
parents:
diff changeset
    24
d425fc41e59f net.cqueues: Add module that allows use of cqueues while still using net.server as main loop
daurnimator <quae@daurnimator.com>
parents:
diff changeset
    25
	-- Use wrapclient (as wrapconnection isn't exported) to get server_select to watch cq fd
d425fc41e59f net.cqueues: Add module that allows use of cqueues while still using net.server as main loop
daurnimator <quae@daurnimator.com>
parents:
diff changeset
    26
	local handler = server.wrapclient({
d425fc41e59f net.cqueues: Add module that allows use of cqueues while still using net.server as main loop
daurnimator <quae@daurnimator.com>
parents:
diff changeset
    27
		getfd = function() return cq:pollfd(); end;
d425fc41e59f net.cqueues: Add module that allows use of cqueues while still using net.server as main loop
daurnimator <quae@daurnimator.com>
parents:
diff changeset
    28
		settimeout = function() end; -- Method just needs to exist
d425fc41e59f net.cqueues: Add module that allows use of cqueues while still using net.server as main loop
daurnimator <quae@daurnimator.com>
parents:
diff changeset
    29
		close = function() end; -- Need close method for 'closeall'
d425fc41e59f net.cqueues: Add module that allows use of cqueues while still using net.server as main loop
daurnimator <quae@daurnimator.com>
parents:
diff changeset
    30
	}, nil, nil, {});
d425fc41e59f net.cqueues: Add module that allows use of cqueues while still using net.server as main loop
daurnimator <quae@daurnimator.com>
parents:
diff changeset
    31
d425fc41e59f net.cqueues: Add module that allows use of cqueues while still using net.server as main loop
daurnimator <quae@daurnimator.com>
parents:
diff changeset
    32
	-- Only need to listen for readable; cqueues handles everything under the hood
d425fc41e59f net.cqueues: Add module that allows use of cqueues while still using net.server as main loop
daurnimator <quae@daurnimator.com>
parents:
diff changeset
    33
	-- readbuffer is called when `select` notes an fd as readable
d425fc41e59f net.cqueues: Add module that allows use of cqueues while still using net.server as main loop
daurnimator <quae@daurnimator.com>
parents:
diff changeset
    34
	handler.readbuffer = step;
d425fc41e59f net.cqueues: Add module that allows use of cqueues while still using net.server as main loop
daurnimator <quae@daurnimator.com>
parents:
diff changeset
    35
d425fc41e59f net.cqueues: Add module that allows use of cqueues while still using net.server as main loop
daurnimator <quae@daurnimator.com>
parents:
diff changeset
    36
	-- Use server_select low lever timer facility,
d425fc41e59f net.cqueues: Add module that allows use of cqueues while still using net.server as main loop
daurnimator <quae@daurnimator.com>
parents:
diff changeset
    37
	-- this callback gets called *every* time there is a timeout in the main loop
d425fc41e59f net.cqueues: Add module that allows use of cqueues while still using net.server as main loop
daurnimator <quae@daurnimator.com>
parents:
diff changeset
    38
	server._addtimer(function(current_time)
d425fc41e59f net.cqueues: Add module that allows use of cqueues while still using net.server as main loop
daurnimator <quae@daurnimator.com>
parents:
diff changeset
    39
		-- This may end up in extra step()'s, but cqueues handles it for us.
d425fc41e59f net.cqueues: Add module that allows use of cqueues while still using net.server as main loop
daurnimator <quae@daurnimator.com>
parents:
diff changeset
    40
		step();
d425fc41e59f net.cqueues: Add module that allows use of cqueues while still using net.server as main loop
daurnimator <quae@daurnimator.com>
parents:
diff changeset
    41
		return cq:timeout();
d425fc41e59f net.cqueues: Add module that allows use of cqueues while still using net.server as main loop
daurnimator <quae@daurnimator.com>
parents:
diff changeset
    42
	end);
d425fc41e59f net.cqueues: Add module that allows use of cqueues while still using net.server as main loop
daurnimator <quae@daurnimator.com>
parents:
diff changeset
    43
elseif server.event and server.base then -- server_event
d425fc41e59f net.cqueues: Add module that allows use of cqueues while still using net.server as main loop
daurnimator <quae@daurnimator.com>
parents:
diff changeset
    44
	cq = cqueues.new();
d425fc41e59f net.cqueues: Add module that allows use of cqueues while still using net.server as main loop
daurnimator <quae@daurnimator.com>
parents:
diff changeset
    45
	-- Only need to listen for readable; cqueues handles everything under the hood
d425fc41e59f net.cqueues: Add module that allows use of cqueues while still using net.server as main loop
daurnimator <quae@daurnimator.com>
parents:
diff changeset
    46
	local EV_READ = server.event.EV_READ;
6540
e4d443d05626 net.cqueues: Fixes hardcoded timeout for first iteration
daurnimator <quae@daurnimator.com>
parents: 6539
diff changeset
    47
	-- Convert a cqueues timeout to an acceptable timeout for luaevent
e4d443d05626 net.cqueues: Fixes hardcoded timeout for first iteration
daurnimator <quae@daurnimator.com>
parents: 6539
diff changeset
    48
	local function luaevent_safe_timeout(cq)
e4d443d05626 net.cqueues: Fixes hardcoded timeout for first iteration
daurnimator <quae@daurnimator.com>
parents: 6539
diff changeset
    49
		local t = cq:timeout();
e4d443d05626 net.cqueues: Fixes hardcoded timeout for first iteration
daurnimator <quae@daurnimator.com>
parents: 6539
diff changeset
    50
		-- if you give luaevent 0 or nil, it re-uses the previous timeout.
e4d443d05626 net.cqueues: Fixes hardcoded timeout for first iteration
daurnimator <quae@daurnimator.com>
parents: 6539
diff changeset
    51
		if t == 0 then
e4d443d05626 net.cqueues: Fixes hardcoded timeout for first iteration
daurnimator <quae@daurnimator.com>
parents: 6539
diff changeset
    52
			t = 0.000001; -- 1 microsecond is the smallest that works (goes into a `struct timeval`)
e4d443d05626 net.cqueues: Fixes hardcoded timeout for first iteration
daurnimator <quae@daurnimator.com>
parents: 6539
diff changeset
    53
		elseif t == nil then -- pick something big if we don't have one
e4d443d05626 net.cqueues: Fixes hardcoded timeout for first iteration
daurnimator <quae@daurnimator.com>
parents: 6539
diff changeset
    54
			t = 0x7FFFFFFF; -- largest 32bit int
e4d443d05626 net.cqueues: Fixes hardcoded timeout for first iteration
daurnimator <quae@daurnimator.com>
parents: 6539
diff changeset
    55
		end
e4d443d05626 net.cqueues: Fixes hardcoded timeout for first iteration
daurnimator <quae@daurnimator.com>
parents: 6539
diff changeset
    56
		return t
e4d443d05626 net.cqueues: Fixes hardcoded timeout for first iteration
daurnimator <quae@daurnimator.com>
parents: 6539
diff changeset
    57
	end
6539
605a87e90e27 net.cqueues: Add workaround for luaevent callback getting collected
daurnimator <quae@daurnimator.com>
parents: 6517
diff changeset
    58
	local event_handle;
605a87e90e27 net.cqueues: Add workaround for luaevent callback getting collected
daurnimator <quae@daurnimator.com>
parents: 6517
diff changeset
    59
	event_handle = server.base:addevent(cq:pollfd(), EV_READ, function(e)
605a87e90e27 net.cqueues: Add workaround for luaevent callback getting collected
daurnimator <quae@daurnimator.com>
parents: 6517
diff changeset
    60
			-- Need to reference event_handle or this callback will get collected
605a87e90e27 net.cqueues: Add workaround for luaevent callback getting collected
daurnimator <quae@daurnimator.com>
parents: 6517
diff changeset
    61
			-- This creates a circular reference that can only be broken if event_handle is manually :close()'d
605a87e90e27 net.cqueues: Add workaround for luaevent callback getting collected
daurnimator <quae@daurnimator.com>
parents: 6517
diff changeset
    62
			local _ = event_handle;
6540
e4d443d05626 net.cqueues: Fixes hardcoded timeout for first iteration
daurnimator <quae@daurnimator.com>
parents: 6539
diff changeset
    63
			-- Run as many cqueues things as possible (with a timeout of 0)
e4d443d05626 net.cqueues: Fixes hardcoded timeout for first iteration
daurnimator <quae@daurnimator.com>
parents: 6539
diff changeset
    64
			-- If an error is thrown, it will break the libevent loop; but prosody resumes after logging a top level error
6517
d425fc41e59f net.cqueues: Add module that allows use of cqueues while still using net.server as main loop
daurnimator <quae@daurnimator.com>
parents:
diff changeset
    65
			assert(cq:loop(0));
6540
e4d443d05626 net.cqueues: Fixes hardcoded timeout for first iteration
daurnimator <quae@daurnimator.com>
parents: 6539
diff changeset
    66
			return EV_READ, luaevent_safe_timeout(cq);
e4d443d05626 net.cqueues: Fixes hardcoded timeout for first iteration
daurnimator <quae@daurnimator.com>
parents: 6539
diff changeset
    67
		end, luaevent_safe_timeout(cq));
6517
d425fc41e59f net.cqueues: Add module that allows use of cqueues while still using net.server as main loop
daurnimator <quae@daurnimator.com>
parents:
diff changeset
    68
else
d425fc41e59f net.cqueues: Add module that allows use of cqueues while still using net.server as main loop
daurnimator <quae@daurnimator.com>
parents:
diff changeset
    69
	error "NYI"
d425fc41e59f net.cqueues: Add module that allows use of cqueues while still using net.server as main loop
daurnimator <quae@daurnimator.com>
parents:
diff changeset
    70
end
d425fc41e59f net.cqueues: Add module that allows use of cqueues while still using net.server as main loop
daurnimator <quae@daurnimator.com>
parents:
diff changeset
    71
d425fc41e59f net.cqueues: Add module that allows use of cqueues while still using net.server as main loop
daurnimator <quae@daurnimator.com>
parents:
diff changeset
    72
return {
d425fc41e59f net.cqueues: Add module that allows use of cqueues while still using net.server as main loop
daurnimator <quae@daurnimator.com>
parents:
diff changeset
    73
	cq = cq;
d425fc41e59f net.cqueues: Add module that allows use of cqueues while still using net.server as main loop
daurnimator <quae@daurnimator.com>
parents:
diff changeset
    74
}