// Copyright 2019 The MediaPipe Authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #include "mediapipe/framework/calculator_context_manager.h" #include #include "absl/memory/memory.h" #include "absl/synchronization/mutex.h" #include "mediapipe/framework/port/logging.h" namespace mediapipe { void CalculatorContextManager::Initialize( CalculatorState* calculator_state, std::shared_ptr input_tag_map, std::shared_ptr output_tag_map, bool calculator_run_in_parallel) { CHECK(calculator_state); calculator_state_ = calculator_state; input_tag_map_ = std::move(input_tag_map); output_tag_map_ = std::move(output_tag_map); calculator_run_in_parallel_ = calculator_run_in_parallel; } absl::Status CalculatorContextManager::PrepareForRun( std::function setup_shards_callback) { setup_shards_callback_ = std::move(setup_shards_callback); default_context_ = absl::make_unique( calculator_state_, input_tag_map_, output_tag_map_); return setup_shards_callback_(default_context_.get()); } void CalculatorContextManager::CleanupAfterRun() { default_context_ = nullptr; absl::MutexLock lock(&contexts_mutex_); active_contexts_.clear(); idle_contexts_.clear(); } CalculatorContext* CalculatorContextManager::GetDefaultCalculatorContext() const { CHECK(default_context_.get()); return default_context_.get(); } CalculatorContext* CalculatorContextManager::GetFrontCalculatorContext( Timestamp* context_input_timestamp) { CHECK(calculator_run_in_parallel_); absl::MutexLock lock(&contexts_mutex_); CHECK(!active_contexts_.empty()); *context_input_timestamp = active_contexts_.begin()->first; return active_contexts_.begin()->second.get(); } CalculatorContext* CalculatorContextManager::PrepareCalculatorContext( Timestamp input_timestamp) { if (!calculator_run_in_parallel_) { return GetDefaultCalculatorContext(); } absl::MutexLock lock(&contexts_mutex_); CHECK(!mediapipe::ContainsKey(active_contexts_, input_timestamp)) << "Multiple invocations with the same timestamps are not allowed with " "parallel execution, input_timestamp = " << input_timestamp; CalculatorContext* calculator_context = nullptr; if (idle_contexts_.empty()) { auto new_context = absl::make_unique( calculator_state_, input_tag_map_, output_tag_map_); MEDIAPIPE_CHECK_OK(setup_shards_callback_(new_context.get())); calculator_context = new_context.get(); active_contexts_.emplace(input_timestamp, std::move(new_context)); } else { // Retrieves an inactive calculator context from idle_contexts_. calculator_context = idle_contexts_.front().get(); active_contexts_.emplace(input_timestamp, std::move(idle_contexts_.front())); idle_contexts_.pop_front(); } return calculator_context; } void CalculatorContextManager::RecycleCalculatorContext() { absl::MutexLock lock(&contexts_mutex_); // The first element in active_contexts_ will be recycled. auto iter = active_contexts_.begin(); idle_contexts_.push_back(std::move(iter->second)); active_contexts_.erase(iter); } bool CalculatorContextManager::HasActiveContexts() { if (!calculator_run_in_parallel_) { return false; } absl::MutexLock lock(&contexts_mutex_); return !active_contexts_.empty(); } } // namespace mediapipe