lib/upnp/Discovery: use std::map instead of std::list

This commit is contained in:
Max Kellermann 2024-01-04 20:35:44 +01:00
parent 3d2aebccad
commit 4ec85a12e3
2 changed files with 23 additions and 38 deletions

View File

@ -21,8 +21,6 @@
class UPnPDeviceDirectory::ContentDirectoryDescriptor { class UPnPDeviceDirectory::ContentDirectoryDescriptor {
public: public:
std::string id;
UPnPDevice device; UPnPDevice device;
/** /**
@ -30,11 +28,9 @@ public:
*/ */
std::chrono::steady_clock::time_point expires; std::chrono::steady_clock::time_point expires;
ContentDirectoryDescriptor(std::string &&_id, ContentDirectoryDescriptor(std::chrono::steady_clock::time_point last,
std::chrono::steady_clock::time_point last,
std::chrono::steady_clock::duration exp) noexcept std::chrono::steady_clock::duration exp) noexcept
:id(std::move(_id)), :expires(last + exp + std::chrono::seconds(20)) {}
expires(last + exp + std::chrono::seconds(20)) {}
void Parse(std::string_view url, std::string_view description) { void Parse(std::string_view url, std::string_view description) {
device.Parse(url, description); device.Parse(url, description);
@ -125,8 +121,7 @@ UPnPDeviceDirectory::Downloader::OnEnd()
{ {
AtScopeExit(this) { Destroy(); }; AtScopeExit(this) { Destroy(); };
ContentDirectoryDescriptor d(std::move(id), ContentDirectoryDescriptor d(std::chrono::steady_clock::now(),
std::chrono::steady_clock::now(),
expires); expires);
try { try {
@ -135,7 +130,7 @@ UPnPDeviceDirectory::Downloader::OnEnd()
LogError(std::current_exception()); LogError(std::current_exception());
} }
parent.LockAdd(std::move(d)); parent.LockAdd(std::move(id), std::move(d));
} }
void void
@ -192,21 +187,14 @@ AnnounceLostUPnP(UPnPDiscoveryListener &listener, const UPnPDevice &device) noex
} }
inline void inline void
UPnPDeviceDirectory::LockAdd(ContentDirectoryDescriptor &&d) noexcept UPnPDeviceDirectory::LockAdd(std::string &&id, ContentDirectoryDescriptor &&d) noexcept
{ {
const std::scoped_lock<Mutex> protect(mutex); const std::scoped_lock<Mutex> protect(mutex);
for (auto &i : directories) { const auto i = directories.insert_or_assign(std::move(id), std::move(d)).first;
if (i.id == d.id) {
i = std::move(d);
return;
}
}
directories.emplace_back(std::move(d));
if (listener != nullptr) if (listener != nullptr)
AnnounceFoundUPnP(*listener, directories.back().device); AnnounceFoundUPnP(*listener, i->second.device);
} }
inline void inline void
@ -214,15 +202,11 @@ UPnPDeviceDirectory::LockRemove(const std::string_view id) noexcept
{ {
const std::scoped_lock<Mutex> protect(mutex); const std::scoped_lock<Mutex> protect(mutex);
for (auto i = directories.begin(), end = directories.end(); if (auto i = directories.find(id); i != directories.end()) {
i != end; ++i) { if (listener != nullptr)
if (i->id == id) { AnnounceLostUPnP(*listener, i->second.device);
if (listener != nullptr)
AnnounceLostUPnP(*listener, i->device);
directories.erase(i); directories.erase(i);
break;
}
} }
} }
@ -290,12 +274,13 @@ UPnPDeviceDirectory::ExpireDevices() noexcept
const auto now = std::chrono::steady_clock::now(); const auto now = std::chrono::steady_clock::now();
bool didsomething = false; bool didsomething = false;
directories.remove_if([now, &didsomething](const ContentDirectoryDescriptor &d){ std::erase_if(directories, [now, &didsomething](const auto &i){
bool expired = now > d.expires; const auto &d = i.second;
if (expired) bool expired = now > d.expires;
didsomething = true; if (expired)
return expired; didsomething = true;
}); return expired;
});
if (didsomething) if (didsomething)
Search(); Search();
@ -357,7 +342,7 @@ UPnPDeviceDirectory::GetDirectories() noexcept
ExpireDevices(); ExpireDevices();
std::vector<ContentDirectoryService> out; std::vector<ContentDirectoryService> out;
for (const auto &descriptor : directories) { for (const auto &[id, descriptor] : directories) {
for (const auto &service : descriptor.device.services) { for (const auto &service : descriptor.device.services) {
if (isCDService(service.serviceType)) { if (isCDService(service.serviceType)) {
out.emplace_back(descriptor.device, service); out.emplace_back(descriptor.device, service);
@ -375,7 +360,7 @@ UPnPDeviceDirectory::GetServer(std::string_view friendly_name)
ExpireDevices(); ExpireDevices();
for (const auto &i : directories) { for (const auto &[id, i] : directories) {
const auto &device = i.device; const auto &device = i.device;
if (device.friendlyName != friendly_name) if (device.friendlyName != friendly_name)

View File

@ -6,7 +6,7 @@
#include "thread/Mutex.hxx" #include "thread/Mutex.hxx"
#include "util/IntrusiveList.hxx" #include "util/IntrusiveList.hxx"
#include <list> #include <map>
#include <vector> #include <vector>
#include <string> #include <string>
#include <chrono> #include <chrono>
@ -49,7 +49,7 @@ class UPnPDeviceDirectory final : UpnpCallback {
/** /**
* Protected by #mutex. * Protected by #mutex.
*/ */
std::list<ContentDirectoryDescriptor> directories; std::map<std::string, ContentDirectoryDescriptor, std::less<>> directories;
/** /**
* The UPnP device search timeout, which should actually be * The UPnP device search timeout, which should actually be
@ -97,7 +97,7 @@ private:
*/ */
void ExpireDevices() noexcept; void ExpireDevices() noexcept;
void LockAdd(ContentDirectoryDescriptor &&d) noexcept; void LockAdd(std::string &&id, ContentDirectoryDescriptor &&d) noexcept;
void LockRemove(std::string_view id) noexcept; void LockRemove(std::string_view id) noexcept;
int OnAlive(const UpnpDiscovery *disco) noexcept; int OnAlive(const UpnpDiscovery *disco) noexcept;