8
8
#include < memory>
9
9
#include < mutex>
10
10
#include < thread>
11
- #include < type_traits>
12
11
#include < vector>
13
12
14
13
#include " flutter/fml/macros.h"
15
14
16
15
namespace impeller {
17
16
18
17
// ------------------------------------------------------------------------------
19
- // / @brief A resource that will be reclaimed by the resource manager. Do
20
- // / not subclass this yourself. Instead, use the `UniqueResourceVKT`
21
- // / template
18
+ // / @brief A resource that may be reclaimed by a |ResourceManagerVK|.
22
19
// /
20
+ // / To create a resource, use `UniqueResourceVKT` to create a unique handle:
21
+ // /
22
+ // / auto resource = UniqueResourceVKT<SomeResource>(resource_manager);
23
+ // /
24
+ // / @see |ResourceManagerVK::Reclaim|.
23
25
class ResourceVK {
24
26
public:
25
27
virtual ~ResourceVK () = default ;
@@ -33,66 +35,95 @@ class ResourceVK {
33
35
// / thread. In the future, the resource manager may allow resource
34
36
// / pooling/reuse, delaying reclamation past frame workloads, etc...
35
37
// /
36
- class ResourceManagerVK
38
+ class ResourceManagerVK final
37
39
: public std::enable_shared_from_this<ResourceManagerVK> {
38
40
public:
39
41
// ----------------------------------------------------------------------------
40
- // / @brief Create a shared resource manager. This creates a dedicated
41
- // / thread for resource management. Only one is created per Vulkan
42
- // / context.
42
+ // / @brief Creates a shared resource manager (a dedicated thread).
43
+ // /
44
+ // / Upon creation, a thread is spawned which will collect resources as they
45
+ // / are reclaimed (passed to `Reclaim`). The thread will exit when the
46
+ // / resource manager is destroyed.
47
+ // /
48
+ // / @note Only one |ResourceManagerVK| should be created per Vulkan
49
+ // / context, but that contract is not enforced by this method.
43
50
// /
44
51
// / @return A resource manager if one could be created.
45
52
// /
46
53
static std::shared_ptr<ResourceManagerVK> Create ();
47
54
48
55
// ----------------------------------------------------------------------------
49
- // / @brief Destroy the resource manager and join all thread. An
50
- // / unreclaimed resources will be destroyed now.
56
+ // / @brief Mark a resource as being reclaimable.
51
57
// /
52
- ~ResourceManagerVK ();
53
-
54
- // ----------------------------------------------------------------------------
55
- // / @brief Mark a resource as being reclaimable by giving ownership of
56
- // / the resource to the resource manager.
58
+ // / The resource will be reset at some point in the future.
57
59
// /
58
60
// / @param[in] resource The resource to reclaim.
59
61
// /
62
+ // / @note Despite being a public API, this method cannot be invoked
63
+ // / directly. Instead, use `UniqueResourceVKT` to create a unique
64
+ // / handle to a resource, which will call this method.
60
65
void Reclaim (std::unique_ptr<ResourceVK> resource);
61
66
62
67
// ----------------------------------------------------------------------------
63
- // / @brief Terminate the resource manager. Any resources given to the
64
- // / resource manager post termination will be collected when the
65
- // / resource manager is collected.
68
+ // / @brief Destroys the resource manager.
66
69
// /
67
- void Terminate ();
70
+ // / The resource manager will stop collecting resources and will be destroyed
71
+ // / when all references to it are dropped.
72
+ ~ResourceManagerVK ();
68
73
69
74
private:
70
- ResourceManagerVK ();
71
-
72
75
using Reclaimables = std::vector<std::unique_ptr<ResourceVK>>;
73
76
77
+ ResourceManagerVK ();
78
+
74
79
std::thread waiter_;
75
80
std::mutex reclaimables_mutex_;
76
81
std::condition_variable reclaimables_cv_;
77
82
Reclaimables reclaimables_;
78
83
bool should_exit_ = false ;
79
84
80
- void Main ();
85
+ // ----------------------------------------------------------------------------
86
+ // / @brief Starts the resource manager thread.
87
+ // /
88
+ // / This method is called implicitly by `Create`.
89
+ void Start ();
90
+
91
+ // ----------------------------------------------------------------------------
92
+ // / @brief Terminates the resource manager thread.
93
+ // /
94
+ // / Any resources given to the resource manager post termination will be
95
+ // / collected when the resource manager is collected.
96
+ void Terminate ();
81
97
82
98
FML_DISALLOW_COPY_AND_ASSIGN (ResourceManagerVK);
83
99
};
84
100
101
+ // ------------------------------------------------------------------------------
102
+ // / @brief An internal type that is used to move a resource reference.
103
+ // /
104
+ // / Do not use directly, use `UniqueResourceVKT` instead.
105
+ // /
106
+ // / @tparam ResourceType_ The type of the resource.
107
+ // /
108
+ // / @see |UniqueResourceVKT|.
85
109
template <class ResourceType_ >
86
110
class ResourceVKT : public ResourceVK {
87
111
public:
88
112
using ResourceType = ResourceType_;
89
113
114
+ // / @brief Construct a resource from a move-constructible resource.
115
+ // /
116
+ // / @param[in] resource The resource to move.
90
117
explicit ResourceVKT (ResourceType&& resource)
91
118
: resource_(std::move(resource)) {}
92
119
120
+ // / @brief Returns a pointer to the resource.
93
121
const ResourceType* Get () const { return &resource_; }
94
122
95
123
private:
124
+ // Prevents subclassing, use `UniqueResourceVKT`.
125
+ ResourceVKT () = default ;
126
+
96
127
ResourceType resource_;
97
128
98
129
FML_DISALLOW_COPY_AND_ASSIGN (ResourceVKT);
@@ -105,13 +136,25 @@ class ResourceVKT : public ResourceVK {
105
136
// / @tparam ResourceType_ A move-constructible resource type.
106
137
// /
107
138
template <class ResourceType_ >
108
- class UniqueResourceVKT {
139
+ class UniqueResourceVKT final {
109
140
public:
110
141
using ResourceType = ResourceType_;
111
142
143
+ // / @brief Construct a unique resource handle belonging to a manager.
144
+ // /
145
+ // / Initially the handle is empty, and can be populated by calling `Swap`.
146
+ // /
147
+ // / @param[in] resource_manager The resource manager.
112
148
explicit UniqueResourceVKT (std::weak_ptr<ResourceManagerVK> resource_manager)
113
149
: resource_manager_(std::move(resource_manager)) {}
114
150
151
+ // / @brief Construct a unique resource handle belonging to a manager.
152
+ // /
153
+ // / Initially the handle is populated with the specified resource, but can
154
+ // / be replaced (reclaiming the old resource) by calling `Swap`.
155
+ // /
156
+ // / @param[in] resource_manager The resource manager.
157
+ // / @param[in] resource The resource to move.
115
158
explicit UniqueResourceVKT (std::weak_ptr<ResourceManagerVK> resource_manager,
116
159
ResourceType&& resource)
117
160
: resource_manager_(std::move(resource_manager)),
@@ -120,19 +163,30 @@ class UniqueResourceVKT {
120
163
121
164
~UniqueResourceVKT () { Reset (); }
122
165
123
- const ResourceType* operator ->() const { return resource_.get ()->Get (); }
166
+ // / @brief Returns a pointer to the resource.
167
+ const ResourceType* operator ->() const {
168
+ // If this would segfault, fail with a nicer error message.
169
+ FML_CHECK (resource_) << " UniqueResourceVKT was reclaimed." ;
170
+
171
+ return resource_.get ()->Get ();
172
+ }
124
173
125
- void Reset (ResourceType&& other) {
174
+ // / @brief Reclaims the existing resource, if any, and replaces it.
175
+ // /
176
+ // / @param[in] other The (new) resource to move.
177
+ void Swap (ResourceType&& other) {
126
178
Reset ();
127
179
resource_ = std::make_unique<ResourceVKT<ResourceType>>(std::move (other));
128
180
}
129
181
182
+ // / @brief Reclaims the existing resource, if any.
130
183
void Reset () {
131
184
if (!resource_) {
132
185
return ;
133
186
}
134
187
// If there is a manager, ask it to reclaim the resource. If there isn't a
135
- // manager, just drop it on the floor here.
188
+ // manager (because the manager has been destroyed), just drop it on the
189
+ // floor here.
136
190
if (auto manager = resource_manager_.lock ()) {
137
191
manager->Reclaim (std::move (resource_));
138
192
}
0 commit comments