diff --git a/src/core/ext/filters/client_channel/client_channel.cc b/src/core/ext/filters/client_channel/client_channel.cc index 01825a14eb9aa8330302a01e21ad0f4ebc614186..450bb5fd04b4ae8137d9d9d4c8c144546ad98691 100644 --- a/src/core/ext/filters/client_channel/client_channel.cc +++ b/src/core/ext/filters/client_channel/client_channel.cc @@ -376,35 +376,39 @@ class CallData { GRPC_ERROR_NONE); } - Iterator Begin() const override { - static_assert(sizeof(grpc_linked_mdelem*) <= sizeof(Iterator), + iterator begin() const override { + static_assert(sizeof(grpc_linked_mdelem*) <= sizeof(intptr_t), "iterator size too large"); - return reinterpret_cast<Iterator>(batch_->list.head); + return iterator(this, reinterpret_cast<intptr_t>(batch_->list.head)); } - bool IsEnd(Iterator it) const override { - return reinterpret_cast<grpc_linked_mdelem*>(it) == nullptr; - } - void Next(Iterator* it) const override { - *it = reinterpret_cast<Iterator>( - reinterpret_cast<grpc_linked_mdelem*>(*it)->next); - } - StringView Key(Iterator it) const override { - return StringView( - GRPC_MDKEY(reinterpret_cast<grpc_linked_mdelem*>(it)->md)); - } - StringView Value(Iterator it) const override { - return StringView( - GRPC_MDVALUE(reinterpret_cast<grpc_linked_mdelem*>(it)->md)); + iterator end() const override { + static_assert(sizeof(grpc_linked_mdelem*) <= sizeof(intptr_t), + "iterator size too large"); + return iterator(this, 0); } - void Erase(Iterator* it) override { + iterator erase(iterator it) override { grpc_linked_mdelem* linked_mdelem = - reinterpret_cast<grpc_linked_mdelem*>(*it); - *it = reinterpret_cast<Iterator>(linked_mdelem->next); + reinterpret_cast<grpc_linked_mdelem*>(GetIteratorHandle(it)); + intptr_t handle = reinterpret_cast<intptr_t>(linked_mdelem->next); grpc_metadata_batch_remove(batch_, linked_mdelem); + return iterator(this, handle); } private: + intptr_t IteratorHandleNext(intptr_t handle) const override { + grpc_linked_mdelem* linked_mdelem = + reinterpret_cast<grpc_linked_mdelem*>(handle); + return reinterpret_cast<intptr_t>(linked_mdelem->next); + } + std::pair<StringView, StringView> IteratorHandleGet( + intptr_t handle) const override { + grpc_linked_mdelem* linked_mdelem = + reinterpret_cast<grpc_linked_mdelem*>(handle); + return std::make_pair(StringView(GRPC_MDKEY(linked_mdelem->md)), + StringView(GRPC_MDVALUE(linked_mdelem->md))); + } + CallData* calld_; grpc_metadata_batch* batch_; }; diff --git a/src/core/ext/filters/client_channel/lb_policy.h b/src/core/ext/filters/client_channel/lb_policy.h index dc4bf51cfce9a34eb5072b57ce784eeebcdcba44..bf6efb00fc1ef56a97478606f7486193977ebc4a 100644 --- a/src/core/ext/filters/client_channel/lb_policy.h +++ b/src/core/ext/filters/client_channel/lb_policy.h @@ -21,6 +21,8 @@ #include <grpc/support/port_platform.h> +#include <iterator> + #include "src/core/ext/filters/client_channel/server_address.h" #include "src/core/ext/filters/client_channel/service_config.h" #include "src/core/ext/filters/client_channel/subchannel_interface.h" @@ -119,10 +121,31 @@ class LoadBalancingPolicy : public InternallyRefCounted<LoadBalancingPolicy> { /// Implemented by the client channel and used by the SubchannelPicker. class MetadataInterface { public: - // Implementations whose iterators fit in intptr_t may internally - // cast this directly to their iterator type. Otherwise, they may - // dynamically allocate their iterators and store the address here. - typedef intptr_t Iterator; + class iterator + : public std::iterator<std::input_iterator_tag, + std::pair<StringView, StringView>, // value_type + std::ptrdiff_t, // difference_type + std::pair<StringView, StringView>*, // pointer + std::pair<StringView, StringView>& // reference + > { + public: + iterator(const MetadataInterface* md, intptr_t handle) + : md_(md), handle_(handle) {} + iterator& operator++() { + handle_ = md_->IteratorHandleNext(handle_); + return *this; + } + bool operator==(iterator other) const { + return md_ == other.md_ && handle_ == other.handle_; + } + bool operator!=(iterator other) const { return !(*this == other); } + value_type operator*() const { return md_->IteratorHandleGet(handle_); } + + private: + friend class MetadataInterface; + const MetadataInterface* md_; + intptr_t handle_; + }; virtual ~MetadataInterface() = default; @@ -134,15 +157,22 @@ class LoadBalancingPolicy : public InternallyRefCounted<LoadBalancingPolicy> { virtual void Add(StringView key, StringView value) = 0; /// Iteration interface. - virtual Iterator Begin() const = 0; - virtual bool IsEnd(Iterator it) const = 0; - virtual void Next(Iterator* it) const = 0; - virtual StringView Key(Iterator it) const = 0; - virtual StringView Value(Iterator it) const = 0; - - /// Removes the element pointed to by \a it, which is modified to - /// point to the next element. - virtual void Erase(Iterator* it) = 0; + virtual iterator begin() const = 0; + virtual iterator end() const = 0; + + /// Removes the element pointed to by \a it. + /// Returns an iterator pointing to the next element. + virtual iterator erase(iterator it) = 0; + + protected: + intptr_t GetIteratorHandle(const iterator& it) const { return it.handle_; } + + private: + friend class iterator; + + virtual intptr_t IteratorHandleNext(intptr_t handle) const = 0; + virtual std::pair<StringView /*key*/, StringView /*value */> + IteratorHandleGet(intptr_t handle) const = 0; }; /// Arguments used when picking a subchannel for a call. diff --git a/test/core/util/test_lb_policies.cc b/test/core/util/test_lb_policies.cc index c4aab3fc3ac540ede8c9895c6094008910da6b8c..684ee656b756a57167d704b19f562791e947ff9b 100644 --- a/test/core/util/test_lb_policies.cc +++ b/test/core/util/test_lb_policies.cc @@ -201,13 +201,10 @@ class InterceptRecvTrailingMetadataLoadBalancingPolicy }; static void LogMetadata(MetadataInterface* metadata) { - for (MetadataInterface::Iterator it = metadata->Begin(); - !metadata->IsEnd(it); metadata->Next(&it)) { + for (const auto& p : *metadata) { gpr_log(GPR_INFO, " \"%.*s\"=>\"%.*s\"", - static_cast<int>(metadata->Key(it).size()), - metadata->Key(it).data(), - static_cast<int>(metadata->Value(it).size()), - metadata->Value(it).data()); + static_cast<int>(p.first.size()), p.first.data(), + static_cast<int>(p.second.size()), p.second.data()); } } };