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