Parcourir la source

resource: remove the requirement to use shared_ptr (close #679)

Michele Caini il y a 5 ans
Parent
commit
0e2afe4f98

+ 1 - 0
TODO

@@ -7,6 +7,7 @@
 * custom pools example (multi instance, tables, enable/disable, and so on...)
 
 WIP:
+* HP: resource, forward the id to the loader from the cache and if constexpr the call to load, update doc and describe customization points
 * HP: any_vector for context variables
 * HP: make const registry::view thread safe, switch to a view<T...>{registry} model (long term goal)
 * HP: review registry::get, registry::try_get

+ 1 - 1
docs/md/resource.md

@@ -23,7 +23,7 @@ loading, and so on.
 `EnTT` doesn't pretend to offer a _one-fits-all_ solution for the different
 cases. Instead, it offers a minimal and perhaps trivial cache that can be useful
 most of the time during prototyping and sometimes even in a production
-environment.<br/>
+environments.<br/>
 For those interested in the subject, the plan is to improve it considerably over
 time in terms of performance, memory usage and functionalities. Hoping to make
 it, of course, one step at a time.

+ 13 - 13
src/entt/resource/cache.hpp

@@ -2,7 +2,6 @@
 #define ENTT_RESOURCE_CACHE_HPP
 
 
-#include <memory>
 #include <type_traits>
 #include <unordered_map>
 #include <utility>
@@ -93,18 +92,16 @@ struct resource_cache {
     template<typename Loader, typename... Args>
     resource_handle<Resource> load(const id_type id, Args &&... args) {
         static_assert(std::is_base_of_v<resource_loader<Loader, Resource>, Loader>, "Invalid loader type");
-        resource_handle<Resource> resource{};
 
         if(auto it = resources.find(id); it == resources.cend()) {
-            if(auto instance = Loader{}.get(std::forward<Args>(args)...); instance) {
-                resources[id] = instance;
-                resource = std::move(instance);
+            if(auto handle = temp<Loader>(std::forward<Args>(args)...); handle) {
+                return (resources[id] = std::move(handle));
             }
         } else {
-            resource = it->second;
+            return it->second;
         }
 
-        return resource;
+        return {};
     }
 
     /**
@@ -149,7 +146,7 @@ struct resource_cache {
      */
     template<typename Loader, typename... Args>
     [[nodiscard]] resource_handle<Resource> temp(Args &&... args) const {
-        return { Loader{}.get(std::forward<Args>(args)...) };
+        return Loader{}.get(std::forward<Args>(args)...);
     }
 
     /**
@@ -166,8 +163,11 @@ struct resource_cache {
      * @return A handle for the given resource.
      */
     [[nodiscard]] resource_handle<Resource> handle(const id_type id) const {
-        auto it = resources.find(id);
-        return { it == resources.end() ? nullptr : it->second };
+        if(auto it = resources.find(id); it != resources.cend()) {
+            return it->second;
+        }
+
+        return {};
     }
 
     /**
@@ -221,15 +221,15 @@ struct resource_cache {
             if constexpr(std::is_invocable_v<Func, id_type>) {
                 func(curr->first);
             } else if constexpr(std::is_invocable_v<Func, resource_handle<Resource>>) {
-                func(resource_handle{ curr->second });
+                func(curr->second);
             } else {
-                func(curr->first, resource_handle{ curr->second });
+                func(curr->first, curr->second);
             }
         }
     }
 
 private:
-    std::unordered_map<id_type, std::shared_ptr<Resource>> resources;
+    std::unordered_map<id_type, resource_handle<Resource>> resources;
 };
 
 

+ 1 - 1
src/entt/resource/fwd.hpp

@@ -10,7 +10,7 @@ struct resource_cache;
 
 
 template<typename>
-class resource_handle;
+struct resource_handle;
 
 
 template<typename, typename>

+ 7 - 7
src/entt/resource/handle.hpp

@@ -24,18 +24,18 @@ namespace entt {
  * @tparam Resource Type of resource managed by a handle.
  */
 template<typename Resource>
-class resource_handle {
-    /*! @brief Resource handles are friends of their caches. */
-    friend struct resource_cache<Resource>;
+struct resource_handle {
+    /*! @brief Default constructor. */
+    resource_handle() ENTT_NOEXCEPT = default;
 
+    /**
+     * @brief Creates a handle from a shared pointer, namely a resource.
+     * @param res A pointer to a properly initialized resource.
+     */
     resource_handle(std::shared_ptr<Resource> res) ENTT_NOEXCEPT
         : resource{std::move(res)}
     {}
 
-public:
-    /*! @brief Default constructor. */
-    resource_handle() ENTT_NOEXCEPT = default;
-
     /**
      * @brief Gets a reference to the managed resource.
      *

+ 4 - 4
src/entt/resource/loader.hpp

@@ -2,8 +2,8 @@
 #define ENTT_RESOURCE_LOADER_HPP
 
 
-#include <memory>
 #include "fwd.hpp"
+#include "handle.hpp"
 
 
 namespace entt {
@@ -15,14 +15,14 @@ namespace entt {
  * Resource loaders must inherit from this class and stay true to the CRTP
  * idiom. Moreover, a resource loader must expose a public, const member
  * function named `load` that accepts a variable number of arguments and returns
- * a shared pointer to the resource just created.<br/>
+ * a handle to the resource just created.<br/>
  * As an example:
  *
  * @code{.cpp}
  * struct my_resource {};
  *
  * struct my_loader: entt::resource_loader<my_loader, my_resource> {
- *     std::shared_ptr<my_resource> load(int) const {
+ *     resource_handle<my_resource> load(int value) const {
  *         // use the integer value somehow
  *         return std::make_shared<my_resource>();
  *     }
@@ -53,7 +53,7 @@ class resource_loader {
      * @return The resource just loaded or an empty pointer in case of errors.
      */
     template<typename... Args>
-    [[nodiscard]] std::shared_ptr<Resource> get(Args &&... args) const {
+    [[nodiscard]] resource_handle<Resource> get(Args &&... args) const {
         return static_cast<const Loader *>(this)->load(std::forward<Args>(args)...);
     }
 };