1 /* 2 * 3 * Copyright 2015 gRPC authors. 4 * 5 * Licensed under the Apache License, Version 2.0 (the "License"); 6 * you may not use this file except in compliance with the License. 7 * You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 * 17 */ 18 19 #ifndef GRPC_CORE_LIB_TRANSPORT_CONNECTIVITY_STATE_H 20 #define GRPC_CORE_LIB_TRANSPORT_CONNECTIVITY_STATE_H 21 22 #include <grpc/support/port_platform.h> 23 24 #include <grpc/grpc.h> 25 26 #include "src/core/lib/debug/trace.h" 27 #include "src/core/lib/gprpp/atomic.h" 28 #include "src/core/lib/gprpp/map.h" 29 #include "src/core/lib/gprpp/orphanable.h" 30 #include "src/core/lib/iomgr/closure.h" 31 #include "src/core/lib/iomgr/exec_ctx.h" 32 #include "src/core/lib/iomgr/work_serializer.h" 33 34 namespace grpc_core { 35 36 extern TraceFlag grpc_connectivity_state_trace; 37 38 // Enum to string conversion. 39 const char* ConnectivityStateName(grpc_connectivity_state state); 40 41 // Interface for watching connectivity state. 42 // Subclasses must implement the Notify() method. 43 // 44 // Note: Most callers will want to use 45 // AsyncConnectivityStateWatcherInterface instead. 46 class ConnectivityStateWatcherInterface 47 : public InternallyRefCounted<ConnectivityStateWatcherInterface> { 48 public: 49 virtual ~ConnectivityStateWatcherInterface() = default; 50 51 // Notifies the watcher that the state has changed to new_state. 52 virtual void Notify(grpc_connectivity_state new_state) = 0; 53 Orphan()54 void Orphan() override { Unref(); } 55 }; 56 57 // An alternative watcher interface that performs notifications via an 58 // asynchronous callback scheduled on the ExecCtx. 59 // Subclasses must implement the OnConnectivityStateChange() method. 60 class AsyncConnectivityStateWatcherInterface 61 : public ConnectivityStateWatcherInterface { 62 public: 63 virtual ~AsyncConnectivityStateWatcherInterface() = default; 64 65 // Schedules a closure on the ExecCtx to invoke 66 // OnConnectivityStateChange() asynchronously. 67 void Notify(grpc_connectivity_state new_state) override final; 68 69 protected: 70 class Notifier; 71 72 // If \a combiner is nullptr, then the notification will be scheduled on the 73 // ExecCtx. 74 explicit AsyncConnectivityStateWatcherInterface( 75 std::shared_ptr<WorkSerializer> work_serializer = nullptr) work_serializer_(std::move (work_serializer))76 : work_serializer_(std::move(work_serializer)) {} 77 78 // Invoked asynchronously when Notify() is called. 79 virtual void OnConnectivityStateChange(grpc_connectivity_state new_state) = 0; 80 81 private: 82 std::shared_ptr<WorkSerializer> work_serializer_; 83 }; 84 85 // Tracks connectivity state. Maintains a list of watchers that are 86 // notified whenever the state changes. 87 // 88 // Note that once the state becomes SHUTDOWN, watchers will be notified 89 // and then automatically orphaned (i.e., RemoveWatcher() does not need 90 // to be called). 91 class ConnectivityStateTracker { 92 public: 93 ConnectivityStateTracker(const char* name, 94 grpc_connectivity_state state = GRPC_CHANNEL_IDLE) name_(name)95 : name_(name), state_(state) {} 96 97 ~ConnectivityStateTracker(); 98 99 // Adds a watcher. 100 // If the current state is different than initial_state, the watcher 101 // will be notified immediately. Otherwise, it will be notified 102 // whenever the state changes. 103 // Not thread safe; access must be serialized with an external lock. 104 void AddWatcher(grpc_connectivity_state initial_state, 105 OrphanablePtr<ConnectivityStateWatcherInterface> watcher); 106 107 // Removes a watcher. The watcher will be orphaned. 108 // Not thread safe; access must be serialized with an external lock. 109 void RemoveWatcher(ConnectivityStateWatcherInterface* watcher); 110 111 // Sets connectivity state. 112 // Not thread safe; access must be serialized with an external lock. 113 void SetState(grpc_connectivity_state state, const char* reason); 114 115 // Gets the current state. 116 // Thread safe; no need to use an external lock. 117 grpc_connectivity_state state() const; 118 119 private: 120 const char* name_; 121 Atomic<grpc_connectivity_state> state_; 122 // TODO(roth): Once we can use C++-14 heterogeneous lookups, this can 123 // be a set instead of a map. 124 std::map<ConnectivityStateWatcherInterface*, 125 OrphanablePtr<ConnectivityStateWatcherInterface>> 126 watchers_; 127 }; 128 129 } // namespace grpc_core 130 131 #endif /* GRPC_CORE_LIB_TRANSPORT_CONNECTIVITY_STATE_H */ 132