Skip to content

CallbackHandler-1.0

CallbackHandler-1.0 is the small dispatch engine that powers the "callback" and "message" systems across the Ace suite: AceEvent-3.0, AceComm-3.0, AceBucket-3.0, AceDB-3.0's profile callbacks, and AceConfigRegistry-3.0 all build on it. You rarely call it directly, but understanding it explains how those callbacks behave.

It has two sides: addon authors register handlers on a library that exposes CallbackHandler methods, and library authors create a registry to fire events into.

For addon authors

When a library is "powered by CallbackHandler", it exposes registration methods, by convention RegisterCallback, UnregisterCallback, and UnregisterAllCallbacks. These are called with a dot and an explicit first argument (your object, or a string addon id) that identifies you as the owner of the registration:

lua
-- e.g. AceDB exposes these on the db object
self.db.RegisterCallback(self, "OnProfileChanged", "RefreshConfig")

function MyAddon:RefreshConfig(event, ...)
    -- event == "OnProfileChanged", followed by any args the library fired
end

Why the dot, and the explicit self

RegisterCallback is not called with :; you pass your self (or an "addonId" string) explicitly as the first argument. CallbackHandler uses it both as the self for method-style handlers and as the key to unregister you later. Calling it as lib:RegisterCallback(...) (passing the library as self) is an error.

How your handler is invoked:

  • method as a string → called as self[method](self, event, ...).
  • method as a function → called as method(event, ...).
  • If you supplied an arg, it is inserted before the event name: self[method](self, arg, event, ...) / method(arg, event, ...).

The first value your handler receives is always the event name (handy for sharing one handler across several events); the firing library's own arguments follow.

RegisterCallback

method#
lua
obj.RegisterCallback(self, eventname, method?, arg?)

Register a handler for an event on a CallbackHandler-powered object. Called with a dot and an explicit self/addon id (see above).

Parameters

ParameterTypeDefaultDescription
selftable | stringYour object (used as the handler's self and as the unregister key), or an "addonId" string when registering a plain function.
eventnamestringThe event/message to listen for.
method (optional)string | functionA method name on self, or a function reference. Defaults to eventname (i.e. a method named after the event).
arg (optional)anyOptional value passed to the handler before the event name.

UnregisterCallback

method#
lua
obj.UnregisterCallback(self, eventname)

Remove a previously registered handler for eventname.

Parameters

ParameterTypeDefaultDescription
selftable | stringThe same object/addon id used to register.
eventnamestringThe event to stop listening for.

UnregisterAllCallbacks

method#
lua
obj.UnregisterAllCallbacks(self)

Remove every callback registered by the given owner. A library may choose not to publish this method.

Parameters

ParameterTypeDefaultDescription
selftable | stringThe object/addon id whose registrations should all be removed.

For library authors

Embed the registration API into your library and get back a registry to fire events through.

New

method#
lua
CallbackHandler:New(target, RegisterName?, UnregisterName?, UnregisterAllName?)

Create a callback registry and embed RegisterName/UnregisterName/UnregisterAllName onto target.

Parameters

ParameterTypeDefaultDescription
targettableThe object to embed the public registration methods into.
RegisterName (optional)stringRegisterCallbackName of the register method to publish.
UnregisterName (optional)stringUnregisterCallbackName of the unregister method to publish.
UnregisterAllName (optional)string | booleanUnregisterAllCallbacksName of the unregister-all method, or false to not publish it.

Returns

TypeDescription
tableThe registry object (with :Fire, and optional OnUsed/OnUnused hooks you can set).

Example

lua
local CallbackHandler = LibStub("CallbackHandler-1.0")

local MyLib = {}
MyLib.callbacks = CallbackHandler:New(MyLib)
-- MyLib.RegisterCallback / UnregisterCallback / UnregisterAllCallbacks now exist

Fire

method#
lua
registry:Fire(eventname, ...)

Fire an event into the registry, invoking every handler registered for eventname.

Registering or unregistering from inside a handler is safe: CallbackHandler queues the change and applies it once the current dispatch finishes.

Parameters

ParameterTypeDefaultDescription
eventnamestringThe event/message to dispatch.
...anyArguments forwarded to every registered handler (after the event name).

Example

lua
function MyLib:DoThing()
    self.callbacks:Fire("OnThingDone", "some", "data")
end
-- a listener's handler receives: (event, "some", "data")

Lazy activation hooks

The registry exposes two optional hooks you can assign. They let a library do expensive setup only while something is actually listening; this is how AceEvent only registers a game event with the client while at least one handler wants it:

  • registry.OnUsed(registry, target, eventname): called when eventname gets its first handler.
  • registry.OnUnused(registry, target, eventname): called when eventname loses its last handler.
lua
function MyLib.callbacks:OnUsed(target, eventname)
    -- start producing eventname (e.g. hook a frame, register a game event)
end
function MyLib.callbacks:OnUnused(target, eventname)
    -- stop producing eventname
end

Ace3, a World of Warcraft addon framework.