ClientList: use class boost::intrusive::list
Eliminate extra allocations for the std::list node instances.
This commit is contained in:
@@ -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;
|
|||||||
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 @@
|
|||||||
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)
|
|||||||
{
|
{
|
||||||
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 @@
|
|||||||
#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:
|
|||||||
}
|
}
|
||||||
|
|
||||||
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,
|
|||||||
|
|
||||||
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,
|
|||||||
|
|
||||||
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)
|
||||||
|
Reference in New Issue
Block a user