/* * Copyright 2023 The WebRTC project authors. All Rights Reserved. * * Use of this source code is governed by a BSD-style license * that can be found in the LICENSE file in the root of the source * tree. An additional intellectual property rights grant can be found * in the file PATENTS. All contributing project authors may * be found in the AUTHORS file in the root of the source tree. */ #include "api/environment/environment_factory.h" #include #include #include #include "api/make_ref_counted.h" #include "api/rtc_event_log/rtc_event_log.h" #include "api/task_queue/default_task_queue_factory.h" #include "api/transport/field_trial_based_config.h" #include "rtc_base/checks.h" #include "system_wrappers/include/clock.h" namespace webrtc { namespace { template void Store(absl::Nonnull> value, scoped_refptr& leaf) { class StorageNode : public rtc::RefCountedBase { public: StorageNode(scoped_refptr parent, absl::Nonnull> value) : parent_(std::move(parent)), value_(std::move(value)) {} StorageNode(const StorageNode&) = delete; StorageNode& operator=(const StorageNode&) = delete; ~StorageNode() override = default; private: scoped_refptr parent_; absl::Nonnull> value_; }; // Utilities provided with ownership form a tree: // Root is nullptr, each node keeps an ownership of one utility. // Each child node has a link to the parent, but parent is unaware of its // children. Each `EnvironmentFactory` and `Environment` keep a reference to a // 'leaf_' - node with the last provided utility. This way `Environment` keeps // ownership of a single branch of the storage tree with each used utiltity // owned by one of the nodes on that branch. leaf = rtc::make_ref_counted(std::move(leaf), std::move(value)); } } // namespace EnvironmentFactory::EnvironmentFactory(const Environment& env) : leaf_(env.storage_), field_trials_(env.field_trials_), clock_(env.clock_), task_queue_factory_(env.task_queue_factory_), event_log_(env.event_log_) {} void EnvironmentFactory::Set( absl::Nullable> utility) { if (utility != nullptr) { field_trials_ = utility.get(); Store(std::move(utility), leaf_); } } void EnvironmentFactory::Set(absl::Nullable> utility) { if (utility != nullptr) { clock_ = utility.get(); Store(std::move(utility), leaf_); } } void EnvironmentFactory::Set( absl::Nullable> utility) { if (utility != nullptr) { task_queue_factory_ = utility.get(); Store(std::move(utility), leaf_); } } void EnvironmentFactory::Set( absl::Nullable> utility) { if (utility != nullptr) { event_log_ = utility.get(); Store(std::move(utility), leaf_); } } Environment EnvironmentFactory::CreateWithDefaults() && { if (field_trials_ == nullptr) { Set(std::make_unique()); } #if defined(WEBRTC_MOZILLA_BUILD) // We want to use our clock, not GetRealTimeClockRaw, and we avoid // building the code under third_party/libwebrtc/task_queue. To // ensure we're setting up things correctly, namely providing an // Environment object with a preset task_queue_factory and clock, // we'll do a release assert here. RTC_CHECK(clock_); RTC_CHECK(task_queue_factory_); #else if (clock_ == nullptr) { Set(Clock::GetRealTimeClock()); } if (task_queue_factory_ == nullptr) { Set(CreateDefaultTaskQueueFactory(field_trials_)); } #endif if (event_log_ == nullptr) { Set(std::make_unique()); } RTC_DCHECK(field_trials_ != nullptr); RTC_DCHECK(clock_ != nullptr); RTC_DCHECK(task_queue_factory_ != nullptr); RTC_DCHECK(event_log_ != nullptr); return Environment(std::move(leaf_), // field_trials_, clock_, task_queue_factory_, event_log_); } Environment EnvironmentFactory::Create() const { // Create a temporary copy to avoid mutating `this` with default utilities. return EnvironmentFactory(*this).CreateWithDefaults(); } } // namespace webrtc