diff --git a/src/Partition.cxx b/src/Partition.cxx index 5c31e9ecd..2e8525a75 100644 --- a/src/Partition.cxx +++ b/src/Partition.cxx @@ -25,6 +25,7 @@ #include "mixer/Volume.hxx" #include "IdleFlags.hxx" #include "client/Listener.hxx" +#include "client/Client.hxx" #include "input/cache/Manager.hxx" #include "util/Domain.hxx" diff --git a/src/Partition.hxx b/src/Partition.hxx index 186ab39e7..3ee2702ca 100644 --- a/src/Partition.hxx +++ b/src/Partition.hxx @@ -32,6 +32,8 @@ #include "Chrono.hxx" #include "config.h" +#include + #include #include @@ -39,6 +41,7 @@ struct Instance; class MultipleOutputs; class SongLoader; class ClientListener; +class Client; /** * A partition of the Music Player Daemon. It is a separate unit with @@ -55,6 +58,11 @@ struct Partition final : QueueListener, PlayerListener, MixerListener { std::unique_ptr listener; + boost::intrusive::list, + boost::intrusive::link_mode>>, + boost::intrusive::constant_time_size> clients; + MaskMonitor global_events; struct playlist playlist; diff --git a/src/client/Client.cxx b/src/client/Client.cxx index 6c47a0822..21bc83cdb 100644 --- a/src/client/Client.cxx +++ b/src/client/Client.cxx @@ -68,7 +68,9 @@ Client::SetPartition(Partition &new_partition) noexcept if (partition == &new_partition) return; + partition->clients.erase(partition->clients.iterator_to(*this)); partition = &new_partition; + partition->clients.push_back(*this); /* set idle flags for those subsystems which are specific to the current partition to force the client to reload its diff --git a/src/client/Client.hxx b/src/client/Client.hxx index e52a7a18a..c94350b51 100644 --- a/src/client/Client.hxx +++ b/src/client/Client.hxx @@ -52,6 +52,8 @@ class BackgroundCommand; class Client final : FullyBufferedSocket, + public boost::intrusive::list_base_hook, + boost::intrusive::link_mode>, public boost::intrusive::list_base_hook> { TimerEvent timeout_event; diff --git a/src/client/New.cxx b/src/client/New.cxx index b1affda4c..1f92c63c3 100644 --- a/src/client/New.cxx +++ b/src/client/New.cxx @@ -72,6 +72,7 @@ client_new(EventLoop &loop, Partition &partition, num); client_list.Add(*client); + partition.clients.push_back(*client); FormatInfo(client_domain, "[%u] opened from %s", num, remote.c_str()); @@ -81,6 +82,7 @@ void Client::Close() noexcept { partition->instance.client_list->Remove(*this); + partition->clients.erase(partition->clients.iterator_to(*this)); if (FullyBufferedSocket::IsDefined()) FullyBufferedSocket::Close(); diff --git a/src/command/MessageCommands.cxx b/src/command/MessageCommands.cxx index c38bc4050..62cf6bb36 100644 --- a/src/command/MessageCommands.cxx +++ b/src/command/MessageCommands.cxx @@ -22,8 +22,8 @@ #include "client/Client.hxx" #include "client/List.hxx" #include "client/Response.hxx" -#include "Instance.hxx" #include "util/ConstBuffer.hxx" +#include "Partition.hxx" #include #include @@ -79,11 +79,7 @@ handle_channels(Client &client, gcc_unused Request args, Response &r) std::set channels; - const auto &partition = client.GetPartition(); - for (const auto &c : *client.GetInstance().client_list) { - if (&c.GetPartition() != &partition) - continue; - + for (const auto &c : client.GetPartition().clients) { const auto &subscriptions = c.GetSubscriptions(); channels.insert(subscriptions.begin(), subscriptions.end()); @@ -125,10 +121,8 @@ handle_send_message(Client &client, Request args, Response &r) bool sent = false; const ClientMessage msg(channel_name, message_text); - const auto &partition = client.GetPartition(); - for (auto &c : *client.GetInstance().client_list) - if (&c.GetPartition() == &partition && - c.PushMessage(msg)) + for (auto &c : client.GetPartition().clients) + if (c.PushMessage(msg)) sent = true; if (sent)