blob: 7a31fd88e62f0933843fc3968b56b61efeff3673 [file] [log] [blame]
#pragma once
#include <algorithm>
#include <array>
#include <mutex>
#include "pw_data_link/socket_data_link.h"
#include "pw_status/status.h"
#include "pw_sync/lock_annotations.h"
#include "pw_sync/mutex.h"
#include "pw_sync/thread_notification.h"
#include "pw_thread/thread_core.h"
#include "pw_thread/yield.h"
namespace pw::data_link {
class SocketDataLinkThread : public pw::thread::ThreadCore {
public:
explicit SocketDataLinkThread(span<SocketDataLink*> active_links)
: active_links_(active_links) {}
pw::Status RegisterLink(SocketDataLink& link) PW_LOCKS_EXCLUDED(lock_) {
std::lock_guard lock(lock_);
auto ptr = std::find(active_links_.begin(), active_links_.end(), nullptr);
if (ptr == active_links_.end()) {
return pw::Status::ResourceExhausted();
}
*ptr = &link;
return pw::OkStatus();
}
pw::Status UnregisterLink(SocketDataLink& link) PW_LOCKS_EXCLUDED(lock_) {
std::lock_guard lock(lock_);
auto ptr = std::find(active_links_.begin(), active_links_.end(), &link);
if (ptr == active_links_.end()) {
return pw::Status::NotFound();
}
*ptr = nullptr;
return pw::OkStatus();
}
void Run() override PW_LOCKS_EXCLUDED(lock_) {
run_ = true;
while (run_) {
std::lock_guard lock(lock_);
for (SocketDataLink* link : active_links_) {
if (link != nullptr) {
link->WaitAndConsumeEvents();
}
}
this_thread::yield();
}
}
void Stop() { run_ = false; }
private:
pw::sync::Mutex lock_;
span<SocketDataLink*> active_links_ PW_GUARDED_BY(lock_);
bool run_ = false;
};
template <size_t max_links>
class SocketDataLinkThreadWithContainer : public SocketDataLinkThread {
public:
SocketDataLinkThreadWithContainer()
: SocketDataLinkThread(active_links_), active_links_{} {}
private:
std::array<SocketDataLink*, max_links> active_links_;
};
} // namespace pw::data_link