• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2021 gRPC authors.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //     http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #include "src/core/config/core_configuration.h"
16 
17 #include <grpc/support/port_platform.h>
18 
19 #include <atomic>
20 #include <utility>
21 #include <vector>
22 
23 #include "absl/log/check.h"
24 
25 namespace grpc_core {
26 
27 std::atomic<CoreConfiguration*> CoreConfiguration::config_{nullptr};
28 std::atomic<CoreConfiguration::RegisteredBuilder*> CoreConfiguration::builders_{
29     nullptr};
30 void (*CoreConfiguration::default_builder_)(CoreConfiguration::Builder*);
31 
32 CoreConfiguration::Builder::Builder() = default;
33 
Build()34 CoreConfiguration* CoreConfiguration::Builder::Build() {
35   return new CoreConfiguration(this);
36 }
37 
CoreConfiguration(Builder * builder)38 CoreConfiguration::CoreConfiguration(Builder* builder)
39     : channel_args_preconditioning_(
40           builder->channel_args_preconditioning_.Build()),
41       channel_init_(builder->channel_init_.Build()),
42       handshaker_registry_(builder->handshaker_registry_.Build()),
43       channel_creds_registry_(builder->channel_creds_registry_.Build()),
44       service_config_parser_(builder->service_config_parser_.Build()),
45       resolver_registry_(builder->resolver_registry_.Build()),
46       lb_policy_registry_(builder->lb_policy_registry_.Build()),
47       proxy_mapper_registry_(builder->proxy_mapper_registry_.Build()),
48       certificate_provider_registry_(
49           builder->certificate_provider_registry_.Build()) {}
50 
RegisterBuilder(absl::AnyInvocable<void (Builder *)> builder)51 void CoreConfiguration::RegisterBuilder(
52     absl::AnyInvocable<void(Builder*)> builder) {
53   CHECK(config_.load(std::memory_order_relaxed) == nullptr)
54       << "CoreConfiguration was already instantiated before builder "
55          "registration was completed";
56   RegisteredBuilder* n = new RegisteredBuilder();
57   n->builder = std::move(builder);
58   n->next = builders_.load(std::memory_order_relaxed);
59   while (!builders_.compare_exchange_weak(n->next, n, std::memory_order_acq_rel,
60                                           std::memory_order_relaxed)) {
61   }
62   CHECK(config_.load(std::memory_order_relaxed) == nullptr)
63       << "CoreConfiguration was already instantiated before builder "
64          "registration was completed";
65 }
66 
BuildNewAndMaybeSet()67 const CoreConfiguration& CoreConfiguration::BuildNewAndMaybeSet() {
68   // Construct builder, pass it up to code that knows about build configuration
69   Builder builder;
70   // The linked list of builders stores things in reverse registration order.
71   // To get things registered as systems relying on this expect however, we
72   // actually need to run things in forward registration order, so we iterate
73   // once over the linked list to build a vector of builders, and then iterate
74   // over said vector in reverse to actually run the builders.
75   std::vector<RegisteredBuilder*> registered_builders;
76   for (RegisteredBuilder* b = builders_.load(std::memory_order_acquire);
77        b != nullptr; b = b->next) {
78     registered_builders.push_back(b);
79   }
80   for (auto it = registered_builders.rbegin(); it != registered_builders.rend();
81        ++it) {
82     (*it)->builder(&builder);
83   }
84   // Finally, call the built in configuration builder.
85   if (default_builder_ != nullptr) (*default_builder_)(&builder);
86   // Use builder to construct a configuration
87   CoreConfiguration* p = builder.Build();
88   // Try to set configuration global - it's possible another thread raced us
89   // here, in which case we drop the work we did and use the one that got set
90   // first
91   CoreConfiguration* expected = nullptr;
92   if (!config_.compare_exchange_strong(expected, p, std::memory_order_acq_rel,
93                                        std::memory_order_acquire)) {
94     delete p;
95     return *expected;
96   }
97   return *p;
98 }
99 
Reset()100 void CoreConfiguration::Reset() {
101   delete config_.exchange(nullptr, std::memory_order_acquire);
102   RegisteredBuilder* builder =
103       builders_.exchange(nullptr, std::memory_order_acquire);
104   while (builder != nullptr) {
105     RegisteredBuilder* next = builder->next;
106     delete builder;
107     builder = next;
108   }
109 }
110 
111 }  // namespace grpc_core
112