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:
+24
-1
@@ -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
@@ -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))
|
||||
|
||||
Reference in New Issue
Block a user