1
0
mirror of https://github.com/unrealircd/unrealircd.git synced 2026-07-07 20:43:13 +02:00

Optimization: use umode_letter_to_handler[] for faster has_user_mode()

and find_user_mode(). That's one array of 256 elements, instead of
iterating a linked list where - if you are unfortunate - one may
need like 26 iterations.

In sendto_channel() we did the check for user mode +T before the
sendflags & SKIP_CTCP, that makes no sense and caused useless CPU.
We now do it the other way around, and also only lookup the user
mode just once (if needed).

The umode_letter_to_handler[] code may crash, it is not well tested
yet, only had two runs so far. Seems to work ok even with REHASH tho,
but have not tested delayed module unloading for example.
This commit is contained in:
Bram Matthys
2025-09-28 16:46:50 +02:00
parent e3b92cc084
commit b3fd6b9bca
2 changed files with 30 additions and 3 deletions
+24 -1
View File
@@ -56,12 +56,15 @@ long SNO_OPER = 0L;
long AllUmodes; /* All umodes */
long SendUmodes; /* All umodes which are sent to other servers (global umodes) */
Umode *umode_letter_to_handler[256];
/* Forward declarations */
int umode_hidle_allow(Client *client, int what);
static void unload_usermode_commit(Umode *m);
void umode_init(void)
{
memset(umode_letter_to_handler, 0, sizeof(umode_letter_to_handler));
/* Some built-in modes */
UmodeAdd(NULL, 'i', UMODE_GLOBAL, 0, umode_allow_all, &UMODE_INVISIBLE);
UmodeAdd(NULL, 'o', UMODE_GLOBAL, 1, umode_allow_opers, &UMODE_OPER);
@@ -81,8 +84,14 @@ void make_umodestr(void)
char *p = umodestring;
for (um=usermodes; um; um = um->next)
{
if (um->letter)
{
*p++ = um->letter;
if (!um->unloaded)
umode_letter_to_handler[um->letter] = um;
}
}
*p = '\0';
}
@@ -116,6 +125,8 @@ void usermode_add_sorted(Umode *n)
{
Umode *m;
umode_letter_to_handler[n->letter] = n;
if (usermodes == NULL)
{
usermodes = n;
@@ -207,6 +218,8 @@ Umode *UmodeAdd(Module *module, char ch, int global, int unset_on_deoper, int (*
um->letter = ch;
um->mode = l;
usermode_add_sorted(um);
} else {
umode_letter_to_handler[um->letter] = um;
}
um->letter = ch;
@@ -318,9 +331,10 @@ static void unload_usermode_commit(Umode *um)
}
/* Then unload the mode */
umode_letter_to_handler[um->letter] = NULL;
DelListItem(um, usermodes);
safe_free(um);
make_umodestr();
make_umodestr(); // this sets umode_letter_to_handler[] properly if a newly loaded module took our handle over
}
void unload_all_unused_umodes(void)
@@ -382,9 +396,18 @@ long find_user_mode(char letter)
{
Umode *um;
#ifndef DEBUGMODE
return umode_letter_to_handler[letter];
#else
/* In debug mode we check for umode_letter_to_handler[] mismatch with list */
for (um = usermodes; um; um = um->next)
if ((um->letter == letter) && !um->unloaded)
{
if (umode_letter_to_handler[letter] != um)
abort();
return um->mode;
}
#endif
return 0;
}
+6 -2
View File
@@ -522,6 +522,10 @@ void sendto_channel(Channel *channel, Client *from, Client *skip,
char member_modes_ext[64];
LineCache *cache;
char check_invisible = 0;
long UMODE_CTCP;
if (sendflags & SKIP_CTCP)
UMODE_CTCP = find_user_mode('T');
if (member_modes)
{
@@ -544,8 +548,8 @@ void sendto_channel(Channel *channel, Client *from, Client *skip,
/* Don't send to deaf clients (unless 'senddeaf' is set) */
if (IsDeaf(acptr) && (sendflags & SKIP_DEAF))
continue;
/* Don't send to NOCTCP clients */
if (has_user_mode(acptr, 'T') && (sendflags & SKIP_CTCP))
/* Don't send to NOCTCP clients (umode +T) */
if ((sendflags & SKIP_CTCP) && (acptr->umodes & UMODE_CTCP))
continue;
/* Sender ('from') is invisible for 'acptr' and we were asked to CHECK_INVISIBLE */
if (check_invisible && !check_channel_access_member(lp, "hoaq") && (from != acptr))