Flutter Engine
The Flutter Engine
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
resource_manager_vk.cc
Go to the documentation of this file.
1// Copyright 2013 The Flutter Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
6
7#include "flutter/fml/cpu_affinity.h"
8#include "flutter/fml/thread.h"
9#include "flutter/fml/trace_event.h"
10#include "fml/logging.h"
11
12namespace impeller {
13
14std::shared_ptr<ResourceManagerVK> ResourceManagerVK::Create() {
15 // It will be tempting to refactor this to create the waiter thread in the
16 // static method instead of the constructor. However, that causes the
17 // destructor never to be called, and the thread never terminates!
18 //
19 // See https://github.com/flutter/flutter/issues/134482.
20 return std::shared_ptr<ResourceManagerVK>(new ResourceManagerVK());
21}
22
23ResourceManagerVK::ResourceManagerVK() : waiter_([&]() { Start(); }) {}
24
26 FML_DCHECK(waiter_.get_id() != std::this_thread::get_id())
27 << "The ResourceManager being destructed on its own spawned thread is a "
28 << "sign that ContextVK was not properly destroyed. A usual fix for this "
29 << "is to ensure that ContextVK is shutdown (i.e. context->Shutdown()) "
30 "before the ResourceManager is destroyed (i.e. at the end of a test).";
31 Terminate();
32 waiter_.join();
33}
34
35void ResourceManagerVK::Start() {
36 // It's possible for Start() to be called when terminating:
37 // { ResourceManagerVK::Create(); }
38 //
39 // ... so no FML_DCHECK here.
40
42 // While this code calls destructors it doesn't need to be particularly fast
43 // with them, as long as it doesn't interrupt raster thread.
45
46 bool should_exit = false;
47 while (!should_exit) {
48 std::unique_lock lock(reclaimables_mutex_);
49
50 // Wait until there are reclaimable resource or if the manager should be
51 // torn down.
52 reclaimables_cv_.wait(
53 lock, [&]() { return !reclaimables_.empty() || should_exit_; });
54
55 // Don't reclaim resources when the lock is being held as this may gate
56 // further reclaimables from being registered.
57 Reclaimables resources_to_collect;
58 std::swap(resources_to_collect, reclaimables_);
59
60 // We can't read the ivar outside the lock. Read it here instead.
61 should_exit = should_exit_;
62
63 // We know what to collect. Unlock before doing anything else.
64 lock.unlock();
65
66 // Claim all resources while tracing.
67 {
68 TRACE_EVENT0("Impeller", "ReclaimResources");
69 resources_to_collect.clear(); // Redundant because of scope but here so
70 // we can add a trace around it.
71 }
72 }
73}
74
75void ResourceManagerVK::Reclaim(std::unique_ptr<ResourceVK> resource) {
76 if (!resource) {
77 return;
78 }
79 {
80 std::scoped_lock lock(reclaimables_mutex_);
81 reclaimables_.emplace_back(std::move(resource));
82 }
83 reclaimables_cv_.notify_one();
84}
85
86void ResourceManagerVK::Terminate() {
87 // The thread should not be terminated more than once.
88 FML_DCHECK(!should_exit_);
89
90 {
91 std::scoped_lock lock(reclaimables_mutex_);
92 should_exit_ = true;
93 }
94 reclaimables_cv_.notify_one();
95}
96
97} // namespace impeller
static SkString resource(SkPDFResourceType type, int index)
void swap(sk_sp< T > &a, sk_sp< T > &b)
Definition: SkRefCnt.h:341
static void SetCurrentThreadName(const ThreadConfig &config)
Definition: thread.cc:135
A resource manager controls how resources are allocated and reclaimed.
static std::shared_ptr< ResourceManagerVK > Create()
Creates a shared resource manager (a dedicated thread).
void Reclaim(std::unique_ptr< ResourceVK > resource)
Mark a resource as being reclaimable.
~ResourceManagerVK()
Destroys the resource manager.
#define FML_DCHECK(condition)
Definition: logging.h:103
@ kEfficiency
Request CPU affinity for the efficiency cores.
bool RequestAffinity(CpuAffinity affinity)
Request the given affinity for the current thread.
Definition: cpu_affinity.cc:26
The ThreadConfig is the thread info include thread name, thread priority.
Definition: thread.h:35
#define TRACE_EVENT0(category_group, name)
Definition: trace_event.h:131