#pragma once #include #include #include #include #include #include "imaging/IPixelariumImage.hpp" namespace pixelarium::resources { using ResourceKey = size_t; /// @brief A dedicated exception to be thrown when a resource of an IResourcePool is empty. struct empty_resource_exception : public std::exception { empty_resource_exception() {}; empty_resource_exception(std::string& msg) : message_(msg) {}; const std::string& what() { return message_; } private: std::string message_ = "Empty Resource"; }; /// @brief Abstract representation of a Resource. /// This is meant to be implemented by arbitrary explicit resource types and thus /// gives no contract other than the abstract type. struct IResource { virtual ~IResource() = default; }; /// @brief Defines a concept for a resource type /// @tparam R The resource template parameter template concept ResT = requires(R& r) { static_cast(r); }; /// @brief Defines an interface for a resource pool /// @tparam ResT defines the resource type that is accepted by the pool template class IResourcePool { public: virtual ~IResourcePool() = default; virtual std::weak_ptr GetResource(size_t id) const = 0; virtual ResourceKey SetResource(std::unique_ptr res) = 0; virtual bool ModifyResource(ResourceKey id, std::unique_ptr res) = 0; virtual bool DeleteResource(ResourceKey id) = 0; virtual void EnumerateResources( const std::function& func) = 0; virtual size_t GetTotalSize() const = 0; virtual void Clear() = 0; }; // Now with the =GetResource= method, I do not want to transfer ownership to the caller of that method. The ownership // should still // reside with the =ResourcePool=! // In fact, the intention is, that there is no way back once the =ResourcePool= took ownership of an object. // Callers can get references, but no ownership. A caller might delete a resource though. class ImageResourcePool : public IResourcePool { public: ImageResourcePool() = default; ImageResourcePool(ImageResourcePool&) = delete; ImageResourcePool(const ImageResourcePool&) = delete; ImageResourcePool(ImageResourcePool&&) = delete; ImageResourcePool& operator=(ImageResourcePool&) = delete; ImageResourcePool& operator=(ImageResourcePool&&) = delete; std::weak_ptr GetResource(ResourceKey id) const override; ResourceKey SetResource(std::unique_ptr res) override; bool ModifyResource(ResourceKey id, std::unique_ptr res) override; bool DeleteResource(ResourceKey id) override; void Clear() override { this->resources_.clear(); } void EnumerateResources( const std::function& func) override; template requires std::invocable void Enumerate(Callable&& func) const { size_t idx{0}; for (const auto& e : this->resources_) { func(e.first, idx, *e.second); } } size_t GetTotalSize() const override { return resources_.size(); } private: std::unordered_map> resources_; std::mutex mut_; }; } // namespace pixelarium::resources