X-Git-Url: https://git.enpas.org/?a=blobdiff_plain;f=util%2Fevents.lua;h=412acccd762cb755a9c0627f2689ea82b5989465;hb=492c253d150aeb7edb6687eb9bf085be6c33133a;hp=b1f3811ca13b2a23231dfec3eb81336bdf791827;hpb=e116081c1d261e25c546a1a98c4207fd5e3fc48e;p=prosody.git diff --git a/util/events.lua b/util/events.lua index b1f3811c..412acccd 100644 --- a/util/events.lua +++ b/util/events.lua @@ -1,96 +1,83 @@ - -local ipairs = ipairs; -local pairs = pairs; -local t_insert = table.insert; -local select = select; - -module "events" - -function new() - local dispatchers = {}; - local handlers = {}; - local event_map = {}; - local function _rebuild_index() -- TODO optimize index rebuilding - for event, _handlers in pairs(event_map) do - local index = handlers[event]; - if index then - for i=#index,1,-1 do index[i] = nil; end - else index = {}; handlers[event] = index; end - for handler in pairs(_handlers) do - t_insert(index, handler); - end - end - end; - local function add_handler(event, handler) - local map = event_map[event]; - if map then - map[handler] = true; - else - map = {[handler] = true}; - event_map[event] = map; - end - _rebuild_index(); - end; - local function remove_handler(event, handler) - local map = event_map[event]; - if map then - map[handler] = nil; - _rebuild_index(); - end - end; - local function add_plugin(plugin) - for event, handler in pairs(plugin) do - add_handler(event, handler); - end - end; - local function remove_plugin(plugin) - for event, handler in pairs(plugin) do - remove_handler(event, handler); - end - end; - local function _create_dispatcher(event) -- FIXME duplicate code in fire_event - local h = handlers[event]; - if not h then h = {}; handlers[event] = h; end - local dispatcher = function(data) - for _, handler in ipairs(h) do - handler(data); - end - end; - dispatchers[event] = dispatcher; - return dispatcher; - end; - local function get_dispatcher(event) - return dispatchers[event] or _create_dispatcher(event); - end; - local function fire_event(event, data) -- FIXME duplicates dispatcher code - local h = handlers[event]; - if h then - for _, handler in ipairs(h) do - handler(data); - end - end - end; - local function get_named_arg_dispatcher(event, ...) - local dispatcher = get_dispatcher(event); - local keys = {...}; - local data = {}; - return function(...) - for i, key in ipairs(keys) do data[key] = select(i, ...); end - dispatcher(data); - end; - end; - return { - add_handler = add_handler; - remove_handler = remove_handler; - add_plugin = add_plugin; - remove_plugin = remove_plugin; - get_dispatcher = get_dispatcher; - fire_event = fire_event; - get_named_arg_dispatcher = get_named_arg_dispatcher; - _dispatchers = dispatchers; - _handlers = handlers; - _event_map = event_map; - }; -end - -return _M; +-- Prosody IM +-- Copyright (C) 2008-2010 Matthew Wild +-- Copyright (C) 2008-2010 Waqas Hussain +-- +-- This project is MIT/X11 licensed. Please see the +-- COPYING file in the source package for more information. +-- + + +local pairs = pairs; +local t_insert = table.insert; +local t_sort = table.sort; +local setmetatable = setmetatable; +local next = next; + +module "events" + +function new() + local handlers = {}; + local event_map = {}; + local function _rebuild_index(handlers, event) + local _handlers = event_map[event]; + if not _handlers or next(_handlers) == nil then return; end + local index = {}; + for handler in pairs(_handlers) do + t_insert(index, handler); + end + t_sort(index, function(a, b) return _handlers[a] > _handlers[b]; end); + handlers[event] = index; + return index; + end; + setmetatable(handlers, { __index = _rebuild_index }); + local function add_handler(event, handler, priority) + local map = event_map[event]; + if map then + map[handler] = priority or 0; + else + map = {[handler] = priority or 0}; + event_map[event] = map; + end + handlers[event] = nil; + end; + local function remove_handler(event, handler) + local map = event_map[event]; + if map then + map[handler] = nil; + handlers[event] = nil; + if next(map) == nil then + event_map[event] = nil; + end + end + end; + local function add_handlers(handlers) + for event, handler in pairs(handlers) do + add_handler(event, handler); + end + end; + local function remove_handlers(handlers) + for event, handler in pairs(handlers) do + remove_handler(event, handler); + end + end; + local function fire_event(event, ...) + local h = handlers[event]; + if h then + for i=1,#h do + local ret = h[i](...); + if ret ~= nil then return ret; end + end + end + end; + return { + add_handler = add_handler; + remove_handler = remove_handler; + add_handlers = add_handlers; + remove_handlers = remove_handlers; + fire_event = fire_event; + _handlers = handlers; + _event_map = event_map; + }; +end + +return _M;