فهرست منبع

resource:
* drop the resource_loader class
* made the loader a template parameter of the resource_cache
* updated the API of the resource_cache

Michele Caini 4 سال پیش
والد
کامیت
b8bb509d5c
6فایلهای تغییر یافته به همراه42 افزوده شده و 107 حذف شده
  1. 0 1
      CMakeLists.txt
  2. 0 1
      src/entt/entt.hpp
  3. 13 13
      src/entt/resource/cache.hpp
  4. 1 1
      src/entt/resource/fwd.hpp
  5. 0 61
      src/entt/resource/loader.hpp
  6. 28 30
      test/entt/resource/resource.cpp

+ 0 - 1
CMakeLists.txt

@@ -171,7 +171,6 @@ if(ENTT_INCLUDE_HEADERS)
             $<BUILD_INTERFACE:${EnTT_SOURCE_DIR}/src/entt/resource/cache.hpp>
             $<BUILD_INTERFACE:${EnTT_SOURCE_DIR}/src/entt/resource/fwd.hpp>
             $<BUILD_INTERFACE:${EnTT_SOURCE_DIR}/src/entt/resource/handle.hpp>
-            $<BUILD_INTERFACE:${EnTT_SOURCE_DIR}/src/entt/resource/loader.hpp>
             $<BUILD_INTERFACE:${EnTT_SOURCE_DIR}/src/entt/signal/delegate.hpp>
             $<BUILD_INTERFACE:${EnTT_SOURCE_DIR}/src/entt/signal/dispatcher.hpp>
             $<BUILD_INTERFACE:${EnTT_SOURCE_DIR}/src/entt/signal/emitter.hpp>

+ 0 - 1
src/entt/entt.hpp

@@ -53,7 +53,6 @@
 #include "process/scheduler.hpp"
 #include "resource/cache.hpp"
 #include "resource/handle.hpp"
-#include "resource/loader.hpp"
 #include "signal/delegate.hpp"
 #include "signal/dispatcher.hpp"
 #include "signal/emitter.hpp"

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

@@ -5,11 +5,11 @@
 #include <utility>
 #include "../config/config.h"
 #include "../container/dense_map.hpp"
+#include "../core/compressed_pair.hpp"
 #include "../core/fwd.hpp"
 #include "../core/utility.hpp"
 #include "fwd.hpp"
 #include "handle.hpp"
-#include "loader.hpp"
 
 namespace entt {
 
@@ -22,16 +22,19 @@ namespace entt {
  * large sized applications.
  *
  * @tparam Resource Type of resources managed by a cache.
+ * @tparam Loader Type of loader used to create the resources.
  */
-template<typename Resource>
+template<typename Resource, typename Loader>
 class resource_cache {
-    static_assert(std::is_same_v<Resource, std::remove_const_t<std::remove_reference_t<Resource>>>, "Invalid resource type");
+    static_assert(std::is_base_of_v<Resource, typename Loader::value_type>, "Invalid loader");
 
 public:
     /*! @brief Unsigned integer type. */
     using size_type = std::size_t;
-    /*! @brief Type of resources managed by a cache. */
+    /*! @brief Resource type. */
     using resource_type = Resource;
+    /*! @brief Loader type. */
+    using loader_type = Loader;
 
     /*! @brief Default constructor. */
     resource_cache() = default;
@@ -84,16 +87,15 @@ public:
      * If the resource cannot be loaded correctly, the returned handle will be
      * invalid and any use of it will result in undefined behavior.
      *
-     * @tparam Loader Type of loader to use to load the resource if required.
      * @tparam Args Types of arguments to use to load the resource if required.
      * @param id Unique resource identifier.
      * @param args Arguments to use to load the resource if required.
      * @return A handle for the given resource.
      */
-    template<typename Loader, typename... Args>
+    template<typename... Args>
     resource_handle<resource_type> load(const id_type id, Args &&...args) {
         if(auto it = resources.find(id); it == resources.cend()) {
-            if(auto handle = temp<Loader>(std::forward<Args>(args)...); handle) {
+            if(auto handle = temp(std::forward<Args>(args)...); handle) {
                 return (resources[id] = std::move(handle));
             }
         } else {
@@ -120,15 +122,14 @@ public:
      * If the resource cannot be loaded correctly, the returned handle will be
      * invalid and any use of it will result in undefined behavior.
      *
-     * @tparam Loader Type of loader to use to load the resource.
      * @tparam Args Types of arguments to use to load the resource.
      * @param id Unique resource identifier.
      * @param args Arguments to use to load the resource.
      * @return A handle for the given resource.
      */
-    template<typename Loader, typename... Args>
+    template<typename... Args>
     resource_handle<resource_type> reload(const id_type id, Args &&...args) {
-        return (discard(id), load<Loader>(id, std::forward<Args>(args)...));
+        return (discard(id), load(id, std::forward<Args>(args)...));
     }
 
     /**
@@ -138,14 +139,13 @@ public:
      * properly the requested resource. The handle isn't stored aside and the
      * cache isn't in charge of the lifetime of the resource itself.
      *
-     * @tparam Loader Type of loader to use to load the resource.
      * @tparam Args Types of arguments to use to load the resource.
      * @param args Arguments to use to load the resource.
      * @return A handle for the given resource.
      */
-    template<typename Loader, typename... Args>
+    template<typename... Args>
     [[nodiscard]] resource_handle<resource_type> temp(Args &&...args) const {
-        return Loader{}.get(std::forward<Args>(args)...);
+        return loader_type{}(std::forward<Args>(args)...);
     }
 
     /**

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

@@ -3,7 +3,7 @@
 
 namespace entt {
 
-template<typename>
+template<typename, typename>
 class resource_cache;
 
 template<typename>

+ 0 - 61
src/entt/resource/loader.hpp

@@ -1,61 +0,0 @@
-#ifndef ENTT_RESOURCE_LOADER_HPP
-#define ENTT_RESOURCE_LOADER_HPP
-
-#include "fwd.hpp"
-#include "handle.hpp"
-
-namespace entt {
-
-/**
- * @brief Base class for resource loaders.
- *
- * 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 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> {
- *     resource_handle<my_resource> load(int value) const {
- *         // use the integer value somehow
- *         return std::make_shared<my_resource>();
- *     }
- * };
- * @endcode
- *
- * In general, resource loaders should not have a state or retain data of any
- * type. They should let the cache manage their resources instead.
- *
- * @note
- * Base class and CRTP idiom aren't strictly required with the current
- * implementation. One could argue that a cache can easily work with loaders of
- * any type. However, future changes won't be breaking ones by forcing the use
- * of a base class today and that's why the model is already in its place.
- *
- * @tparam Loader Type of the derived class.
- * @tparam Resource Type of resource for which to use the loader.
- */
-template<typename Loader, typename Resource>
-class resource_loader {
-    /*! @brief Resource loaders are friends of their caches. */
-    template<typename Other>
-    friend class resource_cache;
-
-    /**
-     * @brief Loads the resource and returns it.
-     * @tparam Args Types of arguments for the loader.
-     * @param args Arguments for the loader.
-     * @return The resource just loaded or an empty pointer in case of errors.
-     */
-    template<typename... Args>
-    [[nodiscard]] resource_handle<Resource> get(Args &&...args) const {
-        return static_cast<const Loader *>(this)->load(std::forward<Args>(args)...);
-    }
-};
-
-} // namespace entt
-
-#endif

+ 28 - 30
test/entt/resource/resource.cpp

@@ -7,7 +7,6 @@
 #include <entt/core/type_info.hpp>
 #include <entt/resource/cache.hpp>
 #include <entt/resource/handle.hpp>
-#include <entt/resource/loader.hpp>
 
 struct resource {
     virtual ~resource() = default;
@@ -26,21 +25,20 @@ struct derived_resource: resource {
 };
 
 template<typename Resource>
-struct loader: entt::resource_loader<loader<Resource>, Resource> {
-    entt::resource_handle<Resource> load(int value) const {
+struct loader {
+    using value_type = Resource;
+
+    entt::resource_handle<Resource> operator()(int value) const {
+        if(value < 0) {
+            return {};
+        }
+
         auto res = std::shared_ptr<Resource>(new Resource);
         res->value = value;
         return res;
     }
 };
 
-template<typename Resource>
-struct broken_loader: entt::resource_loader<broken_loader<Resource>, Resource> {
-    entt::resource_handle<Resource> load(int) const {
-        return {};
-    }
-};
-
 template<typename Type, typename Other>
 entt::resource_handle<Type> dynamic_resource_handle_cast(const entt::resource_handle<Other> &other) {
     if(other->type() == entt::type_id<Type>()) {
@@ -51,7 +49,7 @@ entt::resource_handle<Type> dynamic_resource_handle_cast(const entt::resource_ha
 }
 
 TEST(Resource, Functionalities) {
-    entt::resource_cache<resource> cache;
+    entt::resource_cache<resource, loader<resource>> cache;
 
     constexpr auto hs1 = entt::hashed_string{"res1"};
     constexpr auto hs2 = entt::hashed_string{"res2"};
@@ -61,16 +59,16 @@ TEST(Resource, Functionalities) {
     ASSERT_FALSE(cache.contains(hs1));
     ASSERT_FALSE(cache.contains(hs2));
 
-    ASSERT_FALSE(cache.load<broken_loader<resource>>(hs1, 42));
-    ASSERT_FALSE(cache.reload<broken_loader<resource>>(hs1, 42));
+    ASSERT_FALSE(cache.load(hs1, -1));
+    ASSERT_FALSE(cache.reload(hs1, -1));
 
     ASSERT_EQ(cache.size(), 0u);
     ASSERT_TRUE(cache.empty());
     ASSERT_FALSE(cache.contains(hs1));
     ASSERT_FALSE(cache.contains(hs2));
 
-    ASSERT_TRUE(cache.load<loader<resource>>(hs1, 42));
-    ASSERT_TRUE(cache.reload<loader<resource>>(hs1, 42));
+    ASSERT_TRUE(cache.load(hs1, 42));
+    ASSERT_TRUE(cache.reload(hs1, 42));
 
     ASSERT_EQ(cache.handle(hs1).use_count(), 2);
 
@@ -90,8 +88,8 @@ TEST(Resource, Functionalities) {
     ASSERT_FALSE(cache.contains(hs2));
     ASSERT_EQ((*std::as_const(cache).handle(hs1)).value, 42);
 
-    ASSERT_TRUE(cache.load<loader<resource>>(hs1, 42));
-    ASSERT_TRUE(cache.load<loader<resource>>(hs2, 42));
+    ASSERT_TRUE(cache.load(hs1, 42));
+    ASSERT_TRUE(cache.load(hs2, 42));
 
     ASSERT_NE(cache.size(), 0u);
     ASSERT_FALSE(cache.empty());
@@ -106,7 +104,7 @@ TEST(Resource, Functionalities) {
     ASSERT_TRUE(cache.contains(hs2));
     ASSERT_EQ(cache.handle(hs2)->value, 42);
 
-    ASSERT_TRUE(cache.load<loader<resource>>(hs1, 42));
+    ASSERT_TRUE(cache.load(hs1, 42));
     ASSERT_NO_FATAL_FAILURE(cache.clear());
 
     ASSERT_EQ(cache.size(), 0u);
@@ -114,7 +112,7 @@ TEST(Resource, Functionalities) {
     ASSERT_FALSE(cache.contains(hs1));
     ASSERT_FALSE(cache.contains(hs2));
 
-    ASSERT_TRUE(cache.load<loader<resource>>(hs1, 42));
+    ASSERT_TRUE(cache.load(hs1, 42));
 
     ASSERT_NE(cache.size(), 0u);
     ASSERT_FALSE(cache.empty());
@@ -130,7 +128,7 @@ TEST(Resource, Functionalities) {
     ASSERT_EQ(cache.size(), 0u);
     ASSERT_TRUE(cache.empty());
 
-    ASSERT_TRUE(cache.temp<loader<resource>>(42));
+    ASSERT_TRUE(cache.temp(42));
     ASSERT_TRUE(cache.empty());
 
     ASSERT_FALSE(entt::resource_handle<resource>{});
@@ -141,9 +139,9 @@ TEST(Resource, Functionalities) {
 }
 
 TEST(Resource, ConstNonConstHandle) {
-    entt::resource_cache<resource> cache;
+    entt::resource_cache<resource, loader<resource>> cache;
 
-    entt::resource_handle<resource> handle = cache.temp<loader<resource>>(42);
+    entt::resource_handle<resource> handle = cache.temp(42);
     entt::resource_handle<const resource> chandle = handle;
 
     static_assert(std::is_same_v<decltype(handle.get()), resource &>);
@@ -163,10 +161,10 @@ TEST(Resource, ConstNonConstHandle) {
 }
 
 TEST(Resource, MutableHandle) {
-    entt::resource_cache<resource> cache;
+    entt::resource_cache<resource, loader<resource>> cache;
 
     constexpr auto hs = entt::hashed_string{"res"};
-    auto handle = cache.load<loader<resource>>(hs, 0);
+    auto handle = cache.load(hs, 0);
 
     ASSERT_TRUE(handle);
 
@@ -179,8 +177,8 @@ TEST(Resource, MutableHandle) {
 }
 
 TEST(Resource, HandleImplicitCast) {
-    entt::resource_cache<resource> cache;
-    auto handle = cache.temp<loader<derived_resource>>(0);
+    entt::resource_cache<resource, loader<derived_resource>> cache;
+    auto handle = cache.temp(0);
 
     auto resource = std::make_shared<derived_resource>();
     entt::resource_handle<derived_resource> other{resource};
@@ -216,7 +214,7 @@ TEST(Resource, HandleImplicitCast) {
 }
 
 TEST(Resource, DynamicResourceHandleCast) {
-    entt::resource_handle<derived_resource> handle = entt::resource_cache<derived_resource>{}.temp<loader<derived_resource>>(42);
+    entt::resource_handle<derived_resource> handle = entt::resource_cache<derived_resource, loader<derived_resource>>{}.temp(42);
     entt::resource_handle<const resource> base = handle;
 
     ASSERT_TRUE(base);
@@ -229,7 +227,7 @@ TEST(Resource, DynamicResourceHandleCast) {
     ASSERT_EQ(handle.use_count(), 3u);
     ASSERT_EQ(chandle->value, 42);
 
-    base = entt::resource_cache<resource>{}.temp<loader<resource>>(42);
+    base = entt::resource_cache<resource, loader<resource>>{}.temp(42);
     chandle = dynamic_resource_handle_cast<const derived_resource>(base);
 
     ASSERT_FALSE(chandle);
@@ -239,8 +237,8 @@ TEST(Resource, DynamicResourceHandleCast) {
 TEST(Resource, Each) {
     using namespace entt::literals;
 
-    entt::resource_cache<resource> cache;
-    cache.load<loader<resource>>("resource"_hs, 0);
+    entt::resource_cache<resource, loader<resource>> cache;
+    cache.load("resource"_hs, 0);
 
     cache.each([](entt::resource_handle<resource> res) {
         ++res->value;