Optimize common_channels

git-svn-id: http://svn.inspircd.org/repository/trunk/inspircd@4567 e03df62e-2008-0410-955e-edbf42e46eb7
This commit is contained in:
brain 2006-07-28 11:21:53 +00:00
parent 2696e5f05d
commit e2495e9748

View File

@ -49,30 +49,39 @@ extern time_t TIME;
extern ServerConfig* Config; extern ServerConfig* Config;
/* return 0 or 1 depending if users u and u2 share one or more common channels /* return 0 or 1 depending if users u and u2 share one or more common channels
* (used by QUIT, NICK etc which arent channel specific notices) */ * (used by QUIT, NICK etc which arent channel specific notices)
*
* The old algorithm in 1.0 for this was relatively inefficient, iterating over
* the first users channels then the second users channels within the outer loop,
* therefore it was a maximum of x*y iterations (upon returning 0 and checking
* all possible iterations). However this new function instead checks against the
* channel's userlist in the inner loop which is a std::map<userrec*,userrec*>
* and saves us time as we already know what pointer value we are after.
* Don't quote me on the maths as i am not a mathematician or computer scientist,
* but i believe this algorithm is now x+(log y) maximum iterations instead.
*/
int common_channels(userrec *u, userrec *u2) int common_channels(userrec *u, userrec *u2)
{ {
/* TODO: We need to get rid of this arbitary '7' and make bitmask enums for it */
if ((!u) || (!u2) || (u->registered != 7) || (u2->registered != 7)) if ((!u) || (!u2) || (u->registered != 7) || (u2->registered != 7))
{
return 0; return 0;
}
/* Outer loop */
for (std::vector<ucrec*>::const_iterator i = u->chans.begin(); i != u->chans.end(); i++) for (std::vector<ucrec*>::const_iterator i = u->chans.begin(); i != u->chans.end(); i++)
{ {
for (std::vector<ucrec*>::const_iterator z = u2->chans.begin(); z != u2->chans.end(); z++) /* Fetch the channel from the user */
{ ucrec* user_channel = (ucrec*)(*i);
if ((((ucrec*)(*i))->channel != NULL) && (((ucrec*)(*z))->channel != NULL))
{ if (user_channel->channel)
if ((((ucrec*)(*i))->channel == ((ucrec*)(*z))->channel))
{
if ((c_count(u)) && (c_count(u2)))
{ {
/* Eliminate the inner loop (which used to be ~equal in size to the outer loop)
* by replacing it with a map::find which *should* be more efficient
*/
CUList* channel_user_map = user_channel->channel->GetUsers();
if (channel_user_map->find(u2) != channel_user_map->end())
return 1; return 1;
} }
} }
}
}
}
return 0; return 0;
} }