Commit 3364c1b8 authored by Max Kellermann's avatar Max Kellermann

ClientList: use class boost::intrusive::list

Eliminate extra allocations for the std::list node instances.
parent 0801b3f4
...@@ -27,6 +27,8 @@ ...@@ -27,6 +27,8 @@
#include "event/TimeoutMonitor.hxx" #include "event/TimeoutMonitor.hxx"
#include "Compiler.h" #include "Compiler.h"
#include <boost/intrusive/list.hpp>
#include <set> #include <set>
#include <string> #include <string>
#include <list> #include <list>
...@@ -41,12 +43,20 @@ struct Partition; ...@@ -41,12 +43,20 @@ struct Partition;
class Database; class Database;
class Storage; class Storage;
class Client final : private FullyBufferedSocket, TimeoutMonitor { class Client final
: FullyBufferedSocket, TimeoutMonitor,
public boost::intrusive::list_base_hook<boost::intrusive::link_mode<boost::intrusive::normal_link>> {
public: public:
Partition &partition; Partition &partition;
struct playlist &playlist; struct playlist &playlist;
struct PlayerControl &player_control; struct PlayerControl &player_control;
struct Disposer {
void operator()(Client *client) const {
delete client;
}
};
unsigned permission; unsigned permission;
/** the uid of the client process, or -1 if unknown */ /** the uid of the client process, or -1 if unknown */
......
...@@ -28,28 +28,15 @@ ...@@ -28,28 +28,15 @@
void void
ClientList::Remove(Client &client) ClientList::Remove(Client &client)
{ {
assert(size > 0);
assert(!list.empty()); assert(!list.empty());
auto i = std::find(list.begin(), list.end(), &client); list.erase(list.iterator_to(client));
assert(i != list.end());
list.erase(i);
--size;
} }
void void
ClientList::CloseAll() ClientList::CloseAll()
{ {
while (!list.empty()) { list.clear_and_dispose(Client::Disposer());
delete list.front();
list.pop_front();
#ifndef NDEBUG
--size;
#endif
}
assert(size == 0);
} }
void void
...@@ -57,6 +44,6 @@ ClientList::IdleAdd(unsigned flags) ...@@ -57,6 +44,6 @@ ClientList::IdleAdd(unsigned flags)
{ {
assert(flags != 0); assert(flags != 0);
for (const auto &client : list) for (auto &client : list)
client->IdleAdd(flags); client.IdleAdd(flags);
} }
...@@ -20,21 +20,21 @@ ...@@ -20,21 +20,21 @@
#ifndef MPD_CLIENT_LIST_HXX #ifndef MPD_CLIENT_LIST_HXX
#define MPD_CLIENT_LIST_HXX #define MPD_CLIENT_LIST_HXX
#include <list> #include "Client.hxx"
class Client; class Client;
class ClientList { class ClientList {
typedef std::list<Client *> List; typedef boost::intrusive::list<Client,
boost::intrusive::constant_time_size<true>> List;
const unsigned max_size; const unsigned max_size;
unsigned size;
List list; List list;
public: public:
ClientList(unsigned _max_size) ClientList(unsigned _max_size)
:max_size(_max_size), size(0) {} :max_size(_max_size) {}
~ClientList() { ~ClientList() {
CloseAll(); CloseAll();
} }
...@@ -48,12 +48,11 @@ public: ...@@ -48,12 +48,11 @@ public:
} }
bool IsFull() const { bool IsFull() const {
return size >= max_size; return list.size() >= max_size;
} }
void Add(Client &client) { void Add(Client &client) {
list.push_front(&client); list.push_front(client);
++size;
} }
void Remove(Client &client); void Remove(Client &client);
......
...@@ -82,8 +82,8 @@ handle_channels(Client &client, ...@@ -82,8 +82,8 @@ handle_channels(Client &client,
std::set<std::string> channels; std::set<std::string> channels;
for (const auto &c : *client.partition.instance.client_list) for (const auto &c : *client.partition.instance.client_list)
channels.insert(c->subscriptions.begin(), channels.insert(c.subscriptions.begin(),
c->subscriptions.end()); c.subscriptions.end());
for (const auto &channel : channels) for (const auto &channel : channels)
client_printf(client, "channel: %s\n", channel.c_str()); client_printf(client, "channel: %s\n", channel.c_str());
...@@ -122,8 +122,8 @@ handle_send_message(Client &client, ...@@ -122,8 +122,8 @@ handle_send_message(Client &client,
bool sent = false; bool sent = false;
const ClientMessage msg(argv[1], argv[2]); const ClientMessage msg(argv[1], argv[2]);
for (const auto &c : *client.partition.instance.client_list) for (auto &c : *client.partition.instance.client_list)
if (c->PushMessage(msg)) if (c.PushMessage(msg))
sent = true; sent = true;
if (sent) if (sent)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment