]> git.netwichtig.de Git - user/henk/code/inspircd.git/commitdiff
Convert UserChanList to an intrusively linked list
authorAttila Molnar <attilamolnar@hush.com>
Fri, 24 Jan 2014 11:58:01 +0000 (12:58 +0100)
committerAttila Molnar <attilamolnar@hush.com>
Fri, 24 Jan 2014 11:58:01 +0000 (12:58 +0100)
18 files changed:
include/inspircd.h
include/membership.h
include/modules.h
include/typedefs.h
src/channels.cpp
src/commands/cmd_who.cpp
src/commands/cmd_whois.cpp
src/modules.cpp
src/modules/m_auditorium.cpp
src/modules/m_channelban.cpp
src/modules/m_check.cpp
src/modules/m_delayjoin.cpp
src/modules/m_hostcycle.cpp
src/modules/m_ircv3.cpp
src/modules/m_nickflood.cpp
src/modules/m_nonicks.cpp
src/modules/m_operprefix.cpp
src/users.cpp

index 7a8c1fb748e3f7a8ccb418cd36232d917c954090..897ae9e1809e4aa62e4405632b0777b4bb940c50 100644 (file)
@@ -43,6 +43,7 @@
 #include <string>
 #include <vector>
 
+#include "intrusive_list.h"
 #include "compat.h"
 #include "typedefs.h"
 
index 78af85fde09f8af76ba8d09f27b926438c7eaa58..b0924bef72fe5f6f75d066a627bcb52e3849727b 100644 (file)
@@ -1,6 +1,7 @@
 /*
  * InspIRCd -- Internet Relay Chat Daemon
  *
+ *   Copyright (C) 2012-2014 Attila Molnar <attilamolnar@hush.com>
  *   Copyright (C) 2009 Daniel De Graaf <danieldg@inspircd.org>
  *
  * This file is part of InspIRCd.  InspIRCd is free software: you can
@@ -19,7 +20,7 @@
 
 #pragma once
 
-class CoreExport Membership : public Extensible
+class CoreExport Membership : public Extensible, public intrusive_list_node<Membership>
 {
  public:
        User* const user;
index 7223f6b9d61d139cb87f0952b16cf2fd6f6a1f1f..d221803ab0698214da8fcdbab35c6f2634478233 100644 (file)
@@ -556,7 +556,7 @@ class CoreExport Module : public classbase, public usecountbase
         *
         * Set exceptions[user] = true to include, exceptions[user] = false to exclude
         */
-       virtual void OnBuildNeighborList(User* source, UserChanList &include_c, std::map<User*,bool> &exceptions);
+       virtual void OnBuildNeighborList(User* source, IncludeChanList& include_c, std::map<User*, bool>& exceptions);
 
        /** Called before any nickchange, local or remote. This can be used to implement Q-lines etc.
         * Please note that although you can see remote nickchanges through this function, you should
index 3801a48c0c95481f7036c86154f9a662b0341601..050707e73e38b73337f5534c51f345808bb7f8f2 100644 (file)
@@ -72,12 +72,16 @@ typedef std::vector<reference<ConnectClass> > ClassVector;
 
 /** Typedef for the list of user-channel records for a user
  */
-typedef std::set<Channel*> UserChanList;
+typedef intrusive_list<Membership> UserChanList;
 
 /** Shorthand for an iterator into a UserChanList
  */
 typedef UserChanList::iterator UCListIter;
 
+/** List of channels to consider when building the neighbor list of a user
+ */
+typedef std::vector<Membership*> IncludeChanList;
+
 /** A list of custom modes parameters on a channel
  */
 typedef std::map<char,std::string> CustomModeList;
index 5865f67245d21a0bbcaa8d17bb355a099a2b23d1..7763febd5c9e16a79a980f1da16e7c76b1451b47 100644 (file)
@@ -331,7 +331,7 @@ void Channel::ForceJoin(User* user, const std::string* privs, bool bursting, boo
        if (!memb)
                return; // Already on the channel
 
-       user->chans.insert(this);
+       user->chans.push_front(memb);
 
        if (privs)
        {
@@ -466,7 +466,7 @@ void Channel::PartUser(User *user, std::string &reason)
                WriteAllExcept(user, false, 0, except_list, "PART %s%s%s", this->name.c_str(), reason.empty() ? "" : " :", reason.c_str());
 
                // Remove this channel from the user's chanlist
-               user->chans.erase(this);
+               user->chans.erase(memb);
                // Remove the Membership from this channel's userlist and destroy it
                this->DelUser(membiter);
        }
@@ -520,7 +520,7 @@ void Channel::KickUser(User* src, User* victim, const std::string& reason, Membe
 
        WriteAllExcept(src, false, 0, except_list, "KICK %s %s :%s", name.c_str(), victim->nick.c_str(), reason.c_str());
 
-       victim->chans.erase(this);
+       victim->chans.erase(memb);
        this->DelUser(victimiter);
 }
 
index a059a3f9c8d40ca7e3a1143f3947de14b9418336..37a04af836f6385e3c0d96380d6a5dd027fd459e 100644 (file)
@@ -45,10 +45,9 @@ class CommandWho : public Command
 
        Channel* get_first_visible_channel(User *u)
        {
-               UCListIter i = u->chans.begin();
-               while (i != u->chans.end())
+               for (UCListIter i = u->chans.begin(); i != u->chans.end(); ++i)
                {
-                       Channel* c = *i++;
+                       Channel* c = (*i)->chan;
                        if (!c->IsModeSet(secretmode))
                                return c;
                }
index e8a751fa036dc6ade92b4e63feb1b60eb31572a9..29322f8021b122a6c1e3a4502389a5ebd485305a 100644 (file)
@@ -65,7 +65,7 @@ std::string CommandWhois::ChannelList(User* source, User* dest, bool spy)
 
        for (UCListIter i = dest->chans.begin(); i != dest->chans.end(); i++)
        {
-               Channel* c = *i;
+               Channel* c = (*i)->chan;
                /* If the target is the sender, neither +p nor +s is set, or
                 * the channel contains the user, it is not a spy channel
                 */
index c70a99d779de5d6c2dc559ac008bbe71d84646af..22047ce811e159276a2d37d013e1637139ff234c 100644 (file)
@@ -147,7 +147,7 @@ ModResult   Module::OnChannelPreDelete(Channel*) { DetachEvent(I_OnChannelPreDelet
 void           Module::OnChannelDelete(Channel*) { DetachEvent(I_OnChannelDelete); }
 ModResult      Module::OnSetAway(User*, const std::string &) { DetachEvent(I_OnSetAway); return MOD_RES_PASSTHRU; }
 ModResult      Module::OnWhoisLine(User*, User*, int&, std::string&) { DetachEvent(I_OnWhoisLine); return MOD_RES_PASSTHRU; }
-void           Module::OnBuildNeighborList(User*, UserChanList&, std::map<User*,bool>&) { DetachEvent(I_OnBuildNeighborList); }
+void           Module::OnBuildNeighborList(User*, IncludeChanList&, std::map<User*,bool>&) { DetachEvent(I_OnBuildNeighborList); }
 void           Module::OnGarbageCollect() { DetachEvent(I_OnGarbageCollect); }
 ModResult      Module::OnSetConnectClass(LocalUser* user, ConnectClass* myclass) { DetachEvent(I_OnSetConnectClass); return MOD_RES_PASSTHRU; }
 void           Module::OnText(User*, void*, int, const std::string&, char, CUList&) { DetachEvent(I_OnText); }
index 502a9fb9f1e29f215b0d504790cb3e8c943bba8b..62aa7ec75638601c470e7da8af1b65b682e08877 100644 (file)
@@ -129,19 +129,21 @@ class ModuleAuditorium : public Module
                BuildExcept(memb, excepts);
        }
 
-       void OnBuildNeighborList(User* source, UserChanList &include, std::map<User*,bool> &exception) CXX11_OVERRIDE
+       void OnBuildNeighborList(User* source, IncludeChanList& include, std::map<User*, bool>& exception) CXX11_OVERRIDE
        {
-               UCListIter i = include.begin();
-               while (i != include.end())
+               for (IncludeChanList::iterator i = include.begin(); i != include.end(); )
                {
-                       Channel* c = *i++;
-                       Membership* memb = c->GetUser(source);
-                       if (!memb || IsVisible(memb))
+                       Membership* memb = *i;
+                       if (IsVisible(memb))
+                       {
+                               ++i;
                                continue;
+                       }
+
                        // this channel should not be considered when listing my neighbors
-                       include.erase(c);
+                       i = include.erase(i);
                        // however, that might hide me from ops that can see me...
-                       const UserMembList* users = c->GetUsers();
+                       const UserMembList* users = memb->chan->GetUsers();
                        for(UserMembCIter j = users->begin(); j != users->end(); j++)
                        {
                                if (IS_LOCAL(j->first) && CanSee(j->first, memb))
index 3260c0fa48a0e07f8256f089a07ed98d463a8a79..300caa123c080efd7c222b984d299dfaf8d55b48 100644 (file)
@@ -42,15 +42,9 @@ class ModuleBadChannelExtban : public Module
                        }
                        for (UCListIter i = user->chans.begin(); i != user->chans.end(); i++)
                        {
-                               if (InspIRCd::Match((**i).name, rm))
+                               if (InspIRCd::Match((*i)->chan->name, rm))
                                {
-                                       if (status)
-                                       {
-                                               Membership* memb = (**i).GetUser(user);
-                                               if (memb && memb->hasMode(status))
-                                                       return MOD_RES_DENY;
-                                       }
-                                       else
+                                       if (!status || (*i)->hasMode(status))
                                                return MOD_RES_DENY;
                                }
                        }
index d12d2728d6b30506c1e9e22e94c9e054c1626e7e..c72f88faa404f1a4436056719511406181c390f5 100644 (file)
@@ -192,7 +192,7 @@ class CommandCheck : public Command
 
                        for (UCListIter i = targuser->chans.begin(); i != targuser->chans.end(); i++)
                        {
-                               Channel* c = *i;
+                               Channel* c = (*i)->chan;
                                chliststr.append(c->GetPrefixChar(targuser)).append(c->name).append(" ");
                        }
 
index 70c6b87176aee4e2b555641e657995816db012b6..e183fbe4600041ae581b938ca627c8455fab3df7 100644 (file)
@@ -50,7 +50,7 @@ class ModuleDelayJoin : public Module
        void CleanUser(User* user);
        void OnUserPart(Membership*, std::string &partmessage, CUList&) CXX11_OVERRIDE;
        void OnUserKick(User* source, Membership*, const std::string &reason, CUList&) CXX11_OVERRIDE;
-       void OnBuildNeighborList(User* source, UserChanList &include, std::map<User*,bool> &exception) CXX11_OVERRIDE;
+       void OnBuildNeighborList(User* source, IncludeChanList& include, std::map<User*, bool>& exception) CXX11_OVERRIDE;
        void OnText(User* user, void* dest, int target_type, const std::string &text, char status, CUList &exempt_list) CXX11_OVERRIDE;
        ModResult OnRawMode(User* user, Channel* channel, const char mode, const std::string &param, bool adding, int pcnt) CXX11_OVERRIDE;
 };
@@ -123,15 +123,15 @@ void ModuleDelayJoin::OnUserKick(User* source, Membership* memb, const std::stri
                populate(except, memb);
 }
 
-void ModuleDelayJoin::OnBuildNeighborList(User* source, UserChanList &include, std::map<User*,bool> &exception)
+void ModuleDelayJoin::OnBuildNeighborList(User* source, IncludeChanList& include, std::map<User*, bool>& exception)
 {
-       UCListIter i = include.begin();
-       while (i != include.end())
+       for (IncludeChanList::iterator i = include.begin(); i != include.end(); )
        {
-               Channel* c = *i++;
-               Membership* memb = c->GetUser(source);
-               if (memb && unjoined.get(memb))
-                       include.erase(c);
+               Membership* memb = *i;
+               if (unjoined.get(memb))
+                       i = include.erase(i);
+               else
+                       ++i;
        }
 }
 
index 79b4169ec65f302999d0e9ac217d9e88986761b4..d3646e89935cd71daba33afd6ca9f36e5bcf14d2 100644 (file)
@@ -32,7 +32,7 @@ class ModuleHostCycle : public Module
                already_sent_t silent_id = ++LocalUser::already_sent_id;
                already_sent_t seen_id = ++LocalUser::already_sent_id;
 
-               UserChanList include_chans(user->chans);
+               IncludeChanList include_chans(user->chans.begin(), user->chans.end());
                std::map<User*,bool> exceptions;
 
                FOREACH_MOD(OnBuildNeighborList, (user, include_chans, exceptions));
@@ -56,10 +56,10 @@ class ModuleHostCycle : public Module
 
                std::string newfullhost = user->nick + "!" + newident + "@" + newhost;
 
-               for (UCListIter i = include_chans.begin(); i != include_chans.end(); ++i)
+               for (IncludeChanList::const_iterator i = include_chans.begin(); i != include_chans.end(); ++i)
                {
-                       Channel* c = *i;
-                       Membership* memb = c->GetUser(user);
+                       Membership* memb = *i;
+                       Channel* c = memb->chan;
                        const std::string joinline = ":" + newfullhost + " JOIN " + c->name;
                        std::string modeline;
 
index e8018aea6c1adf79967bc0d616acedb2b5db3b15..5cb2ab6b131bc6f3f51e6ccb02a8311406848f58 100644 (file)
@@ -33,7 +33,7 @@ class ModuleIRCv3 : public Module
 
        void WriteNeighboursWithExt(User* user, const std::string& line, const LocalIntExt& ext)
        {
-               UserChanList chans(user->chans);
+               IncludeChanList chans(user->chans.begin(), user->chans.end());
 
                std::map<User*, bool> exceptions;
                FOREACH_MOD(OnBuildNeighborList, (user, chans, exceptions));
@@ -48,9 +48,9 @@ class ModuleIRCv3 : public Module
 
                // Now consider sending it to all other users who has at least a common channel with the user
                std::set<User*> already_sent;
-               for (UCListIter i = chans.begin(); i != chans.end(); ++i)
+               for (IncludeChanList::const_iterator i = chans.begin(); i != chans.end(); ++i)
                {
-                       const UserMembList* userlist = (*i)->GetUsers();
+                       const UserMembList* userlist = (*i)->chan->GetUsers();
                        for (UserMembList::const_iterator m = userlist->begin(); m != userlist->end(); ++m)
                        {
                                /*
index c3cff2cd18566576962c4cead46e1cda67ec4341..93fbbfaaa7c9838471823675f4b1a33756783225 100644 (file)
@@ -140,7 +140,7 @@ class ModuleNickFlood : public Module
        {
                for (UCListIter i = user->chans.begin(); i != user->chans.end(); i++)
                {
-                       Channel *channel = *i;
+                       Channel* channel = (*i)->chan;
                        ModResult res;
 
                        nickfloodsettings *f = nf.ext.get(channel);
@@ -179,7 +179,7 @@ class ModuleNickFlood : public Module
 
                for (UCListIter i = user->chans.begin(); i != user->chans.end(); ++i)
                {
-                       Channel *channel = *i;
+                       Channel* channel = (*i)->chan;
                        ModResult res;
 
                        nickfloodsettings *f = nf.ext.get(channel);
index a41f509011ffc51ca712fe74f61aaaffb3001ea6..15ee4e7f8371e90bf828df43fa7b00171129ac7b 100644 (file)
@@ -53,7 +53,7 @@ class ModuleNoNickChange : public Module
 
                for (UCListIter i = user->chans.begin(); i != user->chans.end(); i++)
                {
-                       Channel* curr = *i;
+                       Channel* curr = (*i)->chan;
 
                        ModResult res = ServerInstance->OnCheckExemption(user,curr,"nonick");
 
index c84e74892b0142bb48a22f63cca93b9bde4c5b24..4fb4ae942bbcbe501f5c80f34aa8d843198bd2a8 100644 (file)
@@ -81,7 +81,7 @@ class ModuleOperPrefixMode : public Module
                modechange.push_back(user->nick);
                for (UCListIter v = user->chans.begin(); v != user->chans.end(); v++)
                {
-                       modechange[0] = (*v)->name;
+                       modechange[0] = (*v)->chan->name;
                        ServerInstance->Modes->Process(modechange, ServerInstance->FakeClient);
                }
        }
index c855dcad0f917b17b79d971ec5421e6bfffd5dbc..df42d2a9c2910f3e4ad60ddaaa06857dc0b8ac4a 100644 (file)
@@ -682,7 +682,7 @@ bool User::ChangeNick(const std::string& newnick, bool force)
                        {
                                for (UCListIter i = this->chans.begin(); i != this->chans.end(); i++)
                                {
-                                       Channel *chan = *i;
+                                       Channel* chan = (*i)->chan;
                                        if (chan->GetPrefixValue(this) < VOICE_VALUE && chan->IsBanned(this))
                                        {
                                                this->WriteNumeric(ERR_CANNOTSENDTOCHAN, "%s :Cannot send to channel (you're banned)", chan->name.c_str());
@@ -962,7 +962,7 @@ void User::WriteCommonRaw(const std::string &line, bool include_self)
 
        LocalUser::already_sent_id++;
 
-       UserChanList include_c(chans);
+       IncludeChanList include_c(chans.begin(), chans.end());
        std::map<User*,bool> exceptions;
 
        exceptions[this] = include_self;
@@ -979,9 +979,9 @@ void User::WriteCommonRaw(const std::string &line, bool include_self)
                                u->Write(line);
                }
        }
-       for (UCListIter v = include_c.begin(); v != include_c.end(); ++v)
+       for (IncludeChanList::const_iterator v = include_c.begin(); v != include_c.end(); ++v)
        {
-               Channel* c = *v;
+               Channel* c = (*v)->chan;
                const UserMembList* ulist = c->GetUsers();
                for (UserMembList::const_iterator i = ulist->begin(); i != ulist->end(); i++)
                {
@@ -1005,7 +1005,7 @@ void User::WriteCommonQuit(const std::string &normal_text, const std::string &op
        const std::string normalMessage = ":" + this->GetFullHost() + " QUIT :" + normal_text;
        const std::string operMessage = ":" + this->GetFullHost() + " QUIT :" + oper_text;
 
-       UserChanList include_c(chans);
+       IncludeChanList include_c(chans.begin(), chans.end());
        std::map<User*,bool> exceptions;
 
        FOREACH_MOD(OnBuildNeighborList, (this, include_c, exceptions));
@@ -1020,9 +1020,9 @@ void User::WriteCommonQuit(const std::string &normal_text, const std::string &op
                                u->Write(u->IsOper() ? operMessage : normalMessage);
                }
        }
-       for (UCListIter v = include_c.begin(); v != include_c.end(); ++v)
+       for (IncludeChanList::const_iterator v = include_c.begin(); v != include_c.end(); ++v)
        {
-               const UserMembList* ulist = (*v)->GetUsers();
+               const UserMembList* ulist = (*v)->chan->GetUsers();
                for (UserMembList::const_iterator i = ulist->begin(); i != ulist->end(); i++)
                {
                        LocalUser* u = IS_LOCAL(i->first);
@@ -1096,7 +1096,7 @@ bool User::SharesChannelWith(User *other)
                /* 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
                 */
-               if ((*i)->HasUser(other))
+               if ((*i)->chan->HasUser(other))
                        return true;
        }
        return false;
@@ -1277,9 +1277,10 @@ void LocalUser::SetClass(const std::string &explicit_name)
 void User::PurgeEmptyChannels()
 {
        // firstly decrement the count on each channel
-       for (UCListIter f = this->chans.begin(); f != this->chans.end(); f++)
+       for (UCListIter i = this->chans.begin(); i != this->chans.end(); )
        {
-               Channel* c = *f;
+               Channel* c = (*i)->chan;
+               ++i;
                c->DelUser(this);
        }