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 #include <grpc/support/port_platform.h>
20
21 #include "src/core/lib/load_balancing/lb_policy.h"
22
23 #include "src/core/lib/iomgr/closure.h"
24 #include "src/core/lib/iomgr/error.h"
25 #include "src/core/lib/iomgr/exec_ctx.h"
26 #include "src/core/lib/iomgr/pollset_set.h"
27
28 namespace grpc_core {
29
30 DebugOnlyTraceFlag grpc_trace_lb_policy_refcount(false, "lb_policy_refcount");
31
32 //
33 // LoadBalancingPolicy
34 //
35
LoadBalancingPolicy(Args args,intptr_t initial_refcount)36 LoadBalancingPolicy::LoadBalancingPolicy(Args args, intptr_t initial_refcount)
37 : InternallyRefCounted(
38 GRPC_TRACE_FLAG_ENABLED(grpc_trace_lb_policy_refcount)
39 ? "LoadBalancingPolicy"
40 : nullptr,
41 initial_refcount),
42 work_serializer_(std::move(args.work_serializer)),
43 interested_parties_(grpc_pollset_set_create()),
44 channel_control_helper_(std::move(args.channel_control_helper)),
45 channel_args_(std::move(args.args)) {}
46
~LoadBalancingPolicy()47 LoadBalancingPolicy::~LoadBalancingPolicy() {
48 grpc_pollset_set_destroy(interested_parties_);
49 }
50
Orphan()51 void LoadBalancingPolicy::Orphan() {
52 ShutdownLocked();
53 Unref(DEBUG_LOCATION, "Orphan");
54 }
55
56 //
57 // LoadBalancingPolicy::SubchannelPicker
58 //
59
SubchannelPicker()60 LoadBalancingPolicy::SubchannelPicker::SubchannelPicker()
61 : DualRefCounted(GRPC_TRACE_FLAG_ENABLED(grpc_trace_lb_policy_refcount)
62 ? "SubchannelPicker"
63 : nullptr) {}
64
65 //
66 // LoadBalancingPolicy::QueuePicker
67 //
68
Pick(PickArgs)69 LoadBalancingPolicy::PickResult LoadBalancingPolicy::QueuePicker::Pick(
70 PickArgs /*args*/) {
71 // We invoke the parent's ExitIdleLocked() via a closure instead
72 // of doing it directly here because ExitIdleLocked() may cause the
73 // policy's state to change and a new picker to be delivered to the
74 // channel. If that new picker is delivered before ExitIdleLocked()
75 // returns, then by the time this function returns, the pick will already
76 // have been processed, and we'll be trying to re-process the same pick
77 // again, leading to a crash.
78 MutexLock lock(&mu_);
79 if (parent_ != nullptr) {
80 auto* parent = parent_.release(); // ref held by lambda.
81 ExecCtx::Run(DEBUG_LOCATION,
82 GRPC_CLOSURE_CREATE(
83 [](void* arg, grpc_error_handle /*error*/) {
84 auto* parent = static_cast<LoadBalancingPolicy*>(arg);
85 parent->work_serializer()->Run(
86 [parent]() {
87 parent->ExitIdleLocked();
88 parent->Unref();
89 },
90 DEBUG_LOCATION);
91 },
92 parent, nullptr),
93 absl::OkStatus());
94 }
95 return PickResult::Queue();
96 }
97
98 } // namespace grpc_core
99