pw_rpc: Use pw::IntrusiveList for services
Replace the ServiceRegistry and custom intrusive list logic with
pw::IntrusiveList.
Change-Id: Id2b01730593564d167795edd9506a9aa750b45a5
diff --git a/pw_rpc/BUILD b/pw_rpc/BUILD
index ac70d4f..7cf984f 100644
--- a/pw_rpc/BUILD
+++ b/pw_rpc/BUILD
@@ -28,10 +28,8 @@
"base_server_writer.cc",
"public/pw_rpc/internal/base_server_writer.h",
"public/pw_rpc/internal/service.h",
- "public/pw_rpc/internal/service_registry.h",
"server.cc",
"service.cc",
- "service_registry.cc",
],
hdrs = [
"public/pw_rpc/server.h",
diff --git a/pw_rpc/BUILD.gn b/pw_rpc/BUILD.gn
index 28aedf6..9ef034b 100644
--- a/pw_rpc/BUILD.gn
+++ b/pw_rpc/BUILD.gn
@@ -40,11 +40,8 @@
pw_source_set(_target_name) {
forward_variables_from(invoker, "*")
- public_configs = [ ":default_config" ]
public_deps = [
- ":common",
- dir_pw_span,
- dir_pw_status,
+ ":server_library_deps",
implementation,
]
deps = [
@@ -59,10 +56,8 @@
"base_server_writer.cc",
"public/pw_rpc/internal/base_server_writer.h",
"public/pw_rpc/internal/service.h",
- "public/pw_rpc/internal/service_registry.h",
"server.cc",
"service.cc",
- "service_registry.cc",
]
allow_circular_includes_from = [ implementation ]
friend = [ "./*" ]
@@ -80,6 +75,19 @@
}
}
+# Put these dependencies into a group since they need to be shared by the server
+# library and its implementation library.
+group("server_library_deps") {
+ public_configs = [ ":default_config" ]
+ public_deps = [
+ ":common",
+ "$dir_pw_containers:intrusive_list",
+ dir_pw_span,
+ dir_pw_status,
+ ]
+ visibility = [ "./*" ]
+}
+
# Classes with no dependencies on the protobuf library for method invocations.
pw_source_set("common") {
public_configs = [ ":default_config" ]
diff --git a/pw_rpc/nanopb/BUILD.gn b/pw_rpc/nanopb/BUILD.gn
index a8916f4..a8b0cc8 100644
--- a/pw_rpc/nanopb/BUILD.gn
+++ b/pw_rpc/nanopb/BUILD.gn
@@ -27,12 +27,7 @@
public_configs = [ ":config" ]
public = [ "public_overrides/pw_rpc/internal/method.h" ]
sources = [ "method.cc" ]
- public_deps = [
- "../:common",
- dir_pw_assert,
- dir_pw_span,
- dir_pw_status,
- ]
+ public_deps = [ "..:server_library_deps" ]
if (dir_pw_third_party_nanopb != "") {
public_deps += [ dir_pw_third_party_nanopb ]
diff --git a/pw_rpc/public/pw_rpc/internal/service.h b/pw_rpc/public/pw_rpc/internal/service.h
index fb42585..7e5a96f 100644
--- a/pw_rpc/public/pw_rpc/internal/service.h
+++ b/pw_rpc/public/pw_rpc/internal/service.h
@@ -16,6 +16,7 @@
#include <cstdint>
#include <utility>
+#include "pw_containers/intrusive_list.h"
#include "pw_rpc/internal/method.h"
#include "pw_span/span.h"
@@ -23,7 +24,7 @@
// Base class for all RPC services. This cannot be instantiated directly; use a
// generated subclass instead.
-class Service {
+class Service : public IntrusiveList<Service>::Item {
public:
uint32_t id() const { return id_; }
@@ -33,14 +34,13 @@
protected:
template <typename T>
constexpr Service(uint32_t id, T&& methods)
- : id_(id), methods_(std::forward<T>(methods)), next_(nullptr) {}
+ : id_(id), methods_(std::forward<T>(methods)) {}
private:
friend class ServiceRegistry;
uint32_t id_;
span<const Method> methods_;
- Service* next_;
};
} // namespace pw::rpc::internal
diff --git a/pw_rpc/public/pw_rpc/internal/service_registry.h b/pw_rpc/public/pw_rpc/internal/service_registry.h
deleted file mode 100644
index 283a36c..0000000
--- a/pw_rpc/public/pw_rpc/internal/service_registry.h
+++ /dev/null
@@ -1,40 +0,0 @@
-// Copyright 2020 The Pigweed Authors
-//
-// Licensed under the Apache License, Version 2.0 (the "License"); you may not
-// use this file except in compliance with the License. You may obtain a copy of
-// the License at
-//
-// https://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-// License for the specific language governing permissions and limitations under
-// the License.
-#pragma once
-
-#include "pw_assert/assert.h"
-#include "pw_rpc/internal/service.h"
-
-namespace pw::rpc::internal {
-
-// Manages a list of registered RPC services.
-class ServiceRegistry {
- public:
- constexpr ServiceRegistry() : first_service_(nullptr) {}
-
- ServiceRegistry(const ServiceRegistry& other) = delete;
- ServiceRegistry& operator=(const ServiceRegistry& other) = delete;
-
- void Register(Service& service) {
- service.next_ = first_service_;
- first_service_ = &service;
- }
-
- Service* Find(uint32_t id) const;
-
- private:
- Service* first_service_;
-};
-
-} // namespace pw::rpc::internal
diff --git a/pw_rpc/public/pw_rpc/server.h b/pw_rpc/public/pw_rpc/server.h
index 6a9809e..cf4c583 100644
--- a/pw_rpc/public/pw_rpc/server.h
+++ b/pw_rpc/public/pw_rpc/server.h
@@ -15,8 +15,9 @@
#include <cstddef>
+#include "pw_containers/intrusive_list.h"
#include "pw_rpc/channel.h"
-#include "pw_rpc/internal/service_registry.h"
+#include "pw_rpc/internal/service.h"
namespace pw::rpc {
namespace internal {
@@ -37,7 +38,7 @@
// with an internal::Service; instead, use a generated class which inherits
// from it.
void RegisterService(internal::Service& service) {
- services_.Register(service);
+ services_.push_front(service);
}
void ProcessPacket(span<const std::byte> packet, ChannelOutput& interface);
@@ -58,7 +59,7 @@
Channel* AssignChannel(uint32_t id, ChannelOutput& interface);
span<Channel> channels_;
- internal::ServiceRegistry services_;
+ IntrusiveList<internal::Service> services_;
};
} // namespace pw::rpc
diff --git a/pw_rpc/server.cc b/pw_rpc/server.cc
index b239f3d..bc12505 100644
--- a/pw_rpc/server.cc
+++ b/pw_rpc/server.cc
@@ -14,6 +14,8 @@
#include "pw_rpc/server.h"
+#include <algorithm>
+
#include "pw_log/log.h"
#include "pw_rpc/internal/method.h"
#include "pw_rpc/internal/packet.h"
@@ -71,8 +73,11 @@
Channel& channel,
internal::Packet& response,
span<std::byte> buffer) {
- internal::Service* service = services_.Find(request.service_id());
- if (service == nullptr) {
+ auto service = std::find_if(services_.begin(), services_.end(), [&](auto& s) {
+ return s.id() == request.service_id();
+ });
+
+ if (service == services_.end()) {
// Couldn't find the requested service. Reply with a NOT_FOUND response
// without the service_id field set.
response.set_status(Status::NOT_FOUND);
diff --git a/pw_rpc/service_registry.cc b/pw_rpc/service_registry.cc
deleted file mode 100644
index d9182d7..0000000
--- a/pw_rpc/service_registry.cc
+++ /dev/null
@@ -1,28 +0,0 @@
-// Copyright 2020 The Pigweed Authors
-//
-// Licensed under the Apache License, Version 2.0 (the "License"); you may not
-// use this file except in compliance with the License. You may obtain a copy of
-// the License at
-//
-// https://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-// License for the specific language governing permissions and limitations under
-// the License.
-
-#include "pw_rpc/internal/service_registry.h"
-
-namespace pw::rpc::internal {
-
-Service* ServiceRegistry::Find(uint32_t id) const {
- for (Service* s = first_service_; s != nullptr; s = s->next_) {
- if (s->id() == id) {
- return s;
- }
- }
- return nullptr;
-}
-
-} // namespace pw::rpc::internal
diff --git a/pw_rpc/test_impl/BUILD.gn b/pw_rpc/test_impl/BUILD.gn
index 3c050a8..68f88c1 100644
--- a/pw_rpc/test_impl/BUILD.gn
+++ b/pw_rpc/test_impl/BUILD.gn
@@ -25,6 +25,6 @@
pw_source_set("test_impl") {
public_configs = [ ":config" ]
public = [ "public_overrides/pw_rpc/internal/method.h" ]
- public_deps = [ "../:common" ]
+ public_deps = [ "../:server_library_deps" ]
visibility = [ "..:*" ]
}