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