Development/Hooking
From Inspire IRCd (InspIRCd)
| | This page has been marked as Development Material. Information posted here may be subject to change and/or only available in unstable versions of InspIRCd. |
Contents |
[edit]
Hooking Redesign
[edit]
Introduction: What is hooking?
Hooking is the way the IRCd communicates from core to modules, and from modules to modules. e.g. OnUserConnect, and other events.
[edit]
Current Situation
Currently, when an event is called, each module is polled to check whether it contains a handler for an event. If one exists, it is called:
/**
* This #define allows us to call a method in all
* loaded modules in a readable simple way, e.g.:
* 'FOREACH_MOD(I_OnConnect,OnConnect(user));'
*/
#define FOREACH_MOD(y,x) if (ServerInstance->Config->global_implementation[y] > 0) { \
for (int _i = 0; _i <= ServerInstance->GetModuleCount(); _i++) { \
if (ServerInstance->Config->implement_lists[_i][y]) \
try \
{ \
ServerInstance->modules[_i]->x ; \
} \
catch (CoreException& modexcept) \
{ \
ServerInstance->Log(DEFAULT,"Exception cought: %s",modexcept.GetReason()); \
} \
} \
}
While this is okay, it is slow.
[edit]
New Way
Hooks should use an array (or worst case, a map) - where enum Implementation is used as a key. The storage of the array should be an array (or vector?) of pointers of type Module *.
Basically, the buckets are different event types, holding pointers to modules that have registered a hook on that event. :)
This will work almost exactly the same way to the above, but it will be faster.
[19:45] <Brain> ive been giving it some thought
[19:45] <w00t> mm?
[19:45] <Brain> its the next logical thing after oms module loader tidyup
[19:45] <Brain> i want to tie the new priority system and implements system into it
[19:46] <Brain> priority and implements determine both position in those vectors
[19:46] <Brain> and presence in them
[19:46] <Brain> make sense?
[19:46] <Brain> e.g. you can do
[19:46] <Brain> ServerInstance->SetPriority(I_OnUserJoin, this, PRI_FIRST);
[19:46] <Brain> per event priority
[19:46] <Brain> that just bumps your Module* to the start of the list
[19:46] <Brain> (for that event)
[19:47] <Brain> instead of the Implements[x] = 1;
[19:47] <Brain> we do: ServerInstance->Attach(I_OnUserJoin, this);
[19:47] <Brain> we also provide a Detatch() so you can cancel triggering of events on the fly
[19:47] <Brain> both of those just insert and remove from the vectors documented in your hooking doc
[19:47] <Brain> :P
[19:47] <w00t> man oh man, writing out a list of 36 lines of Attach() will suck :P
[19:47] <Brain> nah
[19:48] <Brain> bool Attach (EventType* n, Module* hooker);
[19:48] <Brain> so:
[19:48] <Brain> EventType[] = { I_OnUserJoin, I_OnUserPart ..... };
[19:48] <Brain> ->Attach( ThatArray, this);
[19:48] <Brain> :p
[19:48] <Brain> ;)
[19:49] <Brain> good?
[19:49] <w00t> will they automatically deattach?
[19:49] <Brain> yes
[19:49] <Brain> on unload
[19:49] <w00t> on unload
[19:49] <Brain> but you can detatch
[19:49] <Brain> and re-attach
[19:49] <Brain> at any other time :P
[19:50] <Brain> ofc i'll need help porting all the modules to use Attach
[19:50] <Brain> and i have only 2 days to get the framework of this in before i go to LV
[19:50] <Brain> ohhh, i love a challenge :D
[edit]
New FOREACH_MOD
#define FOREACH_MOD(y,x) \
for (EventHandlerIter _i = ServerInstance->Modules->EventHandlers[y].begin(); _i != ServerInstance->Modules->EventHandlers[y].end(); ++_i) \
{ \
try \
{ \
(*_i)->x ; \
} \
catch (CoreException& modexcept) \
{ \
ServerInstance->Log(DEFAULT,"Exception caught: %s",modexcept.GetReason()); \
} \
}
-- Much better :)
[edit]
New event structure
typedef std::vector<Module*> IntModuleList; IntModuleList EventHandlers[I_END];
- I_END is the enum after the last event type.

















