summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbrain <brain@e03df62e-2008-0410-955e-edbf42e46eb7>2006-07-28 11:21:53 +0000
committerbrain <brain@e03df62e-2008-0410-955e-edbf42e46eb7>2006-07-28 11:21:53 +0000
commite2495e974897eeef3e573daf900134e92106df11 (patch)
tree66f512eec326c0f5135ab9ed2301e8fddbce3649
parent2696e5f05d2e4720706ab12371d56d5dafe0f9ab (diff)
Optimize common_channels
git-svn-id: http://svn.inspircd.org/repository/trunk/inspircd@4567 e03df62e-2008-0410-955e-edbf42e46eb7
-rw-r--r--src/message.cpp39
1 files changed, 24 insertions, 15 deletions
diff --git a/src/message.cpp b/src/message.cpp
index 483cf87d0..a3ca865bf 100644
--- a/src/message.cpp
+++ b/src/message.cpp
@@ -49,28 +49,37 @@ extern time_t TIME;
extern ServerConfig* Config;
/* 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)
{
+ /* 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))
- {
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 z = u2->chans.begin(); z != u2->chans.end(); z++)
+ /* Fetch the channel from the user */
+ ucrec* user_channel = (ucrec*)(*i);
+
+ if (user_channel->channel)
{
- if ((((ucrec*)(*i))->channel != NULL) && (((ucrec*)(*z))->channel != NULL))
- {
- if ((((ucrec*)(*i))->channel == ((ucrec*)(*z))->channel))
- {
- if ((c_count(u)) && (c_count(u2)))
- {
- return 1;
- }
- }
- }
+ /* 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 0;