88#include < memory>
99#include < mutex>
1010#include < thread>
11- #include < type_traits>
1211#include < vector>
1312
1413#include " flutter/fml/macros.h"
1514
1615namespace impeller {
1716
1817// ------------------------------------------------------------------------------
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|.
2219// /
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|.
2325class ResourceVK {
2426 public:
2527 virtual ~ResourceVK () = default ;
@@ -33,66 +35,95 @@ class ResourceVK {
3335// / thread. In the future, the resource manager may allow resource
3436// / pooling/reuse, delaying reclamation past frame workloads, etc...
3537// /
36- class ResourceManagerVK
38+ class ResourceManagerVK final
3739 : public std::enable_shared_from_this<ResourceManagerVK> {
3840 public:
3941 // ----------------------------------------------------------------------------
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.
4350 // /
4451 // / @return A resource manager if one could be created.
4552 // /
4653 static std::shared_ptr<ResourceManagerVK> Create ();
4754
4855 // ----------------------------------------------------------------------------
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.
5157 // /
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.
5759 // /
5860 // / @param[in] resource The resource to reclaim.
5961 // /
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.
6065 void Reclaim (std::unique_ptr<ResourceVK> resource);
6166
6267 // ----------------------------------------------------------------------------
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.
6669 // /
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 ();
6873
6974 private:
70- ResourceManagerVK ();
71-
7275 using Reclaimables = std::vector<std::unique_ptr<ResourceVK>>;
7376
77+ ResourceManagerVK ();
78+
7479 std::thread waiter_;
7580 std::mutex reclaimables_mutex_;
7681 std::condition_variable reclaimables_cv_;
7782 Reclaimables reclaimables_;
7883 bool should_exit_ = false ;
7984
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 ();
8197
8298 FML_DISALLOW_COPY_AND_ASSIGN (ResourceManagerVK);
8399};
84100
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|.
85109template <class ResourceType_ >
86110class ResourceVKT : public ResourceVK {
87111 public:
88112 using ResourceType = ResourceType_;
89113
114+ // / @brief Construct a resource from a move-constructible resource.
115+ // /
116+ // / @param[in] resource The resource to move.
90117 explicit ResourceVKT (ResourceType&& resource)
91118 : resource_(std::move(resource)) {}
92119
120+ // / @brief Returns a pointer to the resource.
93121 const ResourceType* Get () const { return &resource_; }
94122
95123 private:
124+ // Prevents subclassing, use `UniqueResourceVKT`.
125+ ResourceVKT () = default ;
126+
96127 ResourceType resource_;
97128
98129 FML_DISALLOW_COPY_AND_ASSIGN (ResourceVKT);
@@ -105,13 +136,25 @@ class ResourceVKT : public ResourceVK {
105136// / @tparam ResourceType_ A move-constructible resource type.
106137// /
107138template <class ResourceType_ >
108- class UniqueResourceVKT {
139+ class UniqueResourceVKT final {
109140 public:
110141 using ResourceType = ResourceType_;
111142
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.
112148 explicit UniqueResourceVKT (std::weak_ptr<ResourceManagerVK> resource_manager)
113149 : resource_manager_(std::move(resource_manager)) {}
114150
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.
115158 explicit UniqueResourceVKT (std::weak_ptr<ResourceManagerVK> resource_manager,
116159 ResourceType&& resource)
117160 : resource_manager_(std::move(resource_manager)),
@@ -120,19 +163,30 @@ class UniqueResourceVKT {
120163
121164 ~UniqueResourceVKT () { Reset (); }
122165
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+ }
124173
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) {
126178 Reset ();
127179 resource_ = std::make_unique<ResourceVKT<ResourceType>>(std::move (other));
128180 }
129181
182+ // / @brief Reclaims the existing resource, if any.
130183 void Reset () {
131184 if (!resource_) {
132185 return ;
133186 }
134187 // 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.
136190 if (auto manager = resource_manager_.lock ()) {
137191 manager->Reclaim (std::move (resource_));
138192 }
0 commit comments