6b1d68cf8ef0e3ac6351e42244fff8b3757d2e63
[platform/upstream/grpc.git] / src / core / lib / transport / connectivity_state.h
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 "absl/status/status.h"
25
26 #include <grpc/grpc.h>
27
28 #include "src/core/lib/debug/trace.h"
29 #include "src/core/lib/gprpp/atomic.h"
30 #include "src/core/lib/gprpp/map.h"
31 #include "src/core/lib/gprpp/orphanable.h"
32 #include "src/core/lib/iomgr/closure.h"
33 #include "src/core/lib/iomgr/exec_ctx.h"
34 #include "src/core/lib/iomgr/work_serializer.h"
35
36 namespace grpc_core {
37
38 extern TraceFlag grpc_connectivity_state_trace;
39
40 // Enum to string conversion.
41 const char* ConnectivityStateName(grpc_connectivity_state state);
42
43 // Interface for watching connectivity state.
44 // Subclasses must implement the Notify() method.
45 //
46 // Note: Most callers will want to use
47 // AsyncConnectivityStateWatcherInterface instead.
48 class ConnectivityStateWatcherInterface
49     : public InternallyRefCounted<ConnectivityStateWatcherInterface> {
50  public:
51   virtual ~ConnectivityStateWatcherInterface() = default;
52
53   // Notifies the watcher that the state has changed to new_state.
54   virtual void Notify(grpc_connectivity_state new_state,
55                       const absl::Status& status) = 0;
56
57   void Orphan() override { Unref(); }
58 };
59
60 // An alternative watcher interface that performs notifications via an
61 // asynchronous callback scheduled on the ExecCtx.
62 // Subclasses must implement the OnConnectivityStateChange() method.
63 class AsyncConnectivityStateWatcherInterface
64     : public ConnectivityStateWatcherInterface {
65  public:
66   virtual ~AsyncConnectivityStateWatcherInterface() = default;
67
68   // Schedules a closure on the ExecCtx to invoke
69   // OnConnectivityStateChange() asynchronously.
70   void Notify(grpc_connectivity_state new_state,
71               const absl::Status& status) override final;
72
73  protected:
74   class Notifier;
75
76   // If \a work_serializer is nullptr, then the notification will be scheduled
77   // on the ExecCtx.
78   explicit AsyncConnectivityStateWatcherInterface(
79       std::shared_ptr<WorkSerializer> work_serializer = nullptr)
80       : work_serializer_(std::move(work_serializer)) {}
81
82   // Invoked asynchronously when Notify() is called.
83   virtual void OnConnectivityStateChange(grpc_connectivity_state new_state,
84                                          const absl::Status& status) = 0;
85
86  private:
87   std::shared_ptr<WorkSerializer> work_serializer_;
88 };
89
90 // Tracks connectivity state.  Maintains a list of watchers that are
91 // notified whenever the state changes.
92 //
93 // Note that once the state becomes SHUTDOWN, watchers will be notified
94 // and then automatically orphaned (i.e., RemoveWatcher() does not need
95 // to be called).
96 class ConnectivityStateTracker {
97  public:
98   ConnectivityStateTracker(const char* name,
99                            grpc_connectivity_state state = GRPC_CHANNEL_IDLE,
100                            const absl::Status& status = absl::Status())
101       : name_(name), state_(state), status_(status) {}
102
103   ~ConnectivityStateTracker();
104
105   // Adds a watcher.
106   // If the current state is different than initial_state, the watcher
107   // will be notified immediately.  Otherwise, it will be notified
108   // whenever the state changes.
109   // Not thread safe; access must be serialized with an external lock.
110   void AddWatcher(grpc_connectivity_state initial_state,
111                   OrphanablePtr<ConnectivityStateWatcherInterface> watcher);
112
113   // Removes a watcher.  The watcher will be orphaned.
114   // Not thread safe; access must be serialized with an external lock.
115   void RemoveWatcher(ConnectivityStateWatcherInterface* watcher);
116
117   // Sets connectivity state.
118   // Not thread safe; access must be serialized with an external lock.
119   void SetState(grpc_connectivity_state state, const absl::Status& status,
120                 const char* reason);
121
122   // Gets the current state.
123   // Thread safe; no need to use an external lock.
124   grpc_connectivity_state state() const;
125
126   // Get the current status.
127   // Not thread safe; access must be serialized with an external lock.
128   absl::Status status() const { return status_; }
129
130  private:
131   const char* name_;
132   Atomic<grpc_connectivity_state> state_;
133   absl::Status status_;
134   // TODO(roth): Once we can use C++-14 heterogeneous lookups, this can
135   // be a set instead of a map.
136   std::map<ConnectivityStateWatcherInterface*,
137            OrphanablePtr<ConnectivityStateWatcherInterface>>
138       watchers_;
139 };
140
141 }  // namespace grpc_core
142
143 #endif /* GRPC_CORE_LIB_TRANSPORT_CONNECTIVITY_STATE_H */