| // Copyright 2017 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. |
| |
| #ifndef SRC_UI_LIB_ESCHER_RESOURCES_RESOURCE_RECYCLER_H_ |
| #define SRC_UI_LIB_ESCHER_RESOURCES_RESOURCE_RECYCLER_H_ |
| |
| #include <mutex> |
| #include <unordered_map> |
| |
| #include "src/lib/fxl/memory/weak_ptr.h" |
| #include "src/lib/fxl/synchronization/thread_annotations.h" |
| #include "src/ui/lib/escher/impl/command_buffer_sequencer.h" |
| #include "src/ui/lib/escher/resources/resource_manager.h" |
| |
| namespace escher { |
| |
| // Simple manager that keeps resources alive until they are no longer referenced |
| // by a pending command-buffer, then recycles them. It does this by comparing |
| // the sequence numbers from a CommandBufferSequencer with the sequence numbers |
| // of resources that it is keeping alive. The default implementation does not |
| // recycle resources, instead destroying them as soon as it is safe. |
| class ResourceRecycler : public ResourceManager, public impl::CommandBufferSequencerListener { |
| public: |
| explicit ResourceRecycler(EscherWeakPtr escher); |
| |
| virtual ~ResourceRecycler(); |
| |
| fxl::WeakPtr<ResourceRecycler> GetWeakPtr() { return weak_factory_.GetWeakPtr(); } |
| |
| private: |
| // Gives subclasses a chance to recycle the resource. Default implementation |
| // immediately destroys resource. |
| // Note that if OnCommandBufferFinished() and OnReceiveOwnable() is called from multiple threads, |
| // RecycleResource() will also be called from multiple threads, so the implementers should |
| // guarantee thread-safety. |
| virtual void RecycleResource(std::unique_ptr<Resource> resource) {} |
| |
| // Implement impl::CommandBufferSequenceListener::CommandBufferFinished(). |
| // Checks whether it is safe to recycle any of |unused_resources_|. |
| void OnCommandBufferFinished(uint64_t sequence_number) final; |
| |
| // Implement Owner::OnReceiveOwnable(). Call RecycleOwnable() immediately if |
| // it is safe to do so. Otherwise, adds the resource to a set of resources |
| // to be recycled later; see CommandBufferFinished(). |
| void OnReceiveOwnable(std::unique_ptr<Resource> resource) final; |
| |
| uint64_t last_finished_sequence_number_ = 0; |
| |
| // This mutex protects access to |unused_resources_|. These class methods |
| // may be called from multiple threads. |
| mutable std::mutex lock_; |
| |
| // We need to use an unordered_map instead of an unordered_set because you |
| // can't modify elements of an unordered_set, which prevents us from |
| // removing a unique_ptr. |
| std::unordered_map<Resource*, std::unique_ptr<Resource>> unused_resources_ FXL_GUARDED_BY(lock_); |
| |
| fxl::WeakPtrFactory<ResourceRecycler> weak_factory_; // must be last |
| |
| FXL_DISALLOW_COPY_AND_ASSIGN(ResourceRecycler); |
| }; |
| |
| } // namespace escher |
| |
| #endif // SRC_UI_LIB_ESCHER_RESOURCES_RESOURCE_RECYCLER_H_ |