| // Copyright 2016 The Fuchsia Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "lib/escher/impl/vk/pipeline_cache.h" |
| |
| namespace escher { |
| namespace impl { |
| |
| PipelineCache::PipelineCache() {} |
| |
| PipelineCache::~PipelineCache() {} |
| |
| std::shared_future<PipelinePtr> PipelineCache::GetPipeline( |
| const PipelineSpec& spec, const PipelineFactoryPtr& factory) { |
| std::lock_guard<std::mutex> lock(mutex_); |
| auto it = map_.find(spec); |
| if (it != map_.end()) { |
| // The pipeline already exists, or someone else is in the process of |
| // creating it. Either way, return the stashed future. |
| return it->second; |
| } |
| |
| // The pipeline has not been requested; create a new one. |
| |
| // Create a promise that we will asynchronously resolve. We must store it in |
| // a shared_ptr because we cannot move it into the lambda, since functions are |
| // copyable and promise is move-only. |
| auto promise = std::make_shared<std::promise<PipelinePtr>>(); |
| |
| // Obtain the shared-future that we will return from this function, and stash |
| // a copy in the map. |
| auto result = promise->get_future().share(); |
| map_[spec] = result; |
| |
| // Wait for the factory on another thread. |
| std::thread([spec, factory, promise{move(promise)}]() { |
| auto pipeline = factory->NewPipeline(std::move(spec)).get(); |
| // If this fails, then subsequent requests for the same spec are |
| // guaranteed to fail forever. |
| FXL_DCHECK(pipeline); |
| promise->set_value(std::move(pipeline)); |
| }).detach(); |
| |
| return result; |
| } |
| |
| } // namespace impl |
| } // namespace escher |