e2e-examples/gcs/sample/channel_manager.h (55 lines of code) (raw):

// Copyright 2022 gRPC 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 // // http://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. #ifndef GCS_SAMPLE_CHANNEL_MANAGER_H_ #define GCS_SAMPLE_CHANNEL_MANAGER_H_ #include <grpcpp/channel.h> #include <memory> #include "absl/memory/memory.h" #include "absl/strings/string_view.h" #include "absl/synchronization/mutex.h" #include "absl/time/time.h" #include "google/storage/v2/storage.grpc.pb.h" class ChannelManager; // This is to track a lifetime of rpc call. This is supposed to // be used for a single RPC. ChannelManager assumes that users // will use this to make a single RPC call and call OnRpcDone // with its call status. This instance should be short-lived. // // For example: // auto handle = channel_manager.GetHandle(); // handle.GetStub<RpcStub>().RpcCall(...) // handle.OnRpcDone(status); class ChannelHandle { private: ChannelHandle(ChannelManager* manager, std::shared_ptr<grpc::Channel> channel); public: ~ChannelHandle(); // Move-only object ChannelHandle(ChannelHandle&&) = default; ChannelHandle& operator=(ChannelHandle&&) = default; ChannelHandle(const ChannelHandle&) = delete; ChannelHandle& operator=(const ChannelHandle&) = delete; // Returns a stub instance of given type. template <typename T> std::unique_ptr<T> GetStub() { assert(!on_rpc_done_called_); return absl::make_unique<T>(channel_); } // When a RPC gets response, this function needs to be called so that // a channel manager can notice this call finished. void OnRpcDone(grpc::Status status); private: ChannelManager* manager_; std::shared_ptr<grpc::Channel> channel_; bool on_rpc_done_called_; friend class ChannelManager; }; // This manages a channel pool and tracks the usage of each channel. // Using this usage information, a manage can manage to pick the best // channel for the next rpc call. When this instance destroys, all // ChannelHandle instances created from this should be destroyed. class ChannelManager { public: ChannelManager( // The maximum number of channels in the pool size_t max_channel_count, // A function to create a gRPC channel std::function<std::shared_ptr<grpc::Channel>()> channel_creator); ~ChannelManager(); // Returns the ChannelHandle to be used to make a rpc call. ChannelHandle GetHandle(); private: void OnRpcDone(grpc::Channel* channel, grpc::Status status); void OnChannelHandleDestroyed(grpc::Channel* channel); private: struct ChannelState { std::shared_ptr<grpc::Channel> channel; // The number of in-progress RPC. size_t in_use_count; }; absl::Mutex lock_; size_t max_channel_count_; size_t channel_handle_count_; std::function<std::shared_ptr<grpc::Channel>()> channel_creator_; std::vector<ChannelState> channel_states_; friend class ChannelHandle; }; #endif // GCS_SAMPLE_CHANNEL_MANAGER_H_