1 #pragma once 2 3 4 #include <memory> 5 #include <type_traits> 6 #include <utility> 7 #include "loop.hpp" 8 9 10 namespace uvw { 11 12 13 /** 14 * @brief Wrapper class for underlying types. 15 * 16 * It acts mainly as a wrapper around data structures of the underlying library. 17 */ 18 template<typename T, typename U> 19 class UnderlyingType { 20 template<typename, typename> 21 friend class UnderlyingType; 22 23 protected: ConstructorAccessuvw::UnderlyingType::ConstructorAccess24 struct ConstructorAccess { explicit ConstructorAccess(int) {} }; 25 get()26 auto get() noexcept { 27 return &resource; 28 } 29 get() const30 auto get() const noexcept { 31 return &resource; 32 } 33 34 template<typename R> get()35 auto get() noexcept { 36 static_assert(not std::is_same<R, U>::value, "!"); 37 return reinterpret_cast<R *>(&resource); 38 } 39 40 template<typename R, typename... P> get(UnderlyingType<P...> & other)41 auto get(UnderlyingType<P...> &other) noexcept { 42 return reinterpret_cast<R *>(&other.resource); 43 } 44 45 template<typename R> get() const46 auto get() const noexcept { 47 static_assert(not std::is_same<R, U>::value, "!"); 48 return reinterpret_cast<const R *>(&resource); 49 } 50 51 template<typename R, typename... P> get(const UnderlyingType<P...> & other) const52 auto get(const UnderlyingType<P...> &other) const noexcept { 53 return reinterpret_cast<const R *>(&other.resource); 54 } 55 56 public: UnderlyingType(ConstructorAccess,std::shared_ptr<Loop> ref)57 explicit UnderlyingType(ConstructorAccess, std::shared_ptr<Loop> ref) noexcept 58 : pLoop{std::move(ref)}, resource{} 59 {} 60 61 UnderlyingType(const UnderlyingType &) = delete; 62 UnderlyingType(UnderlyingType &&) = delete; 63 ~UnderlyingType()64 virtual ~UnderlyingType() { 65 static_assert(std::is_base_of<UnderlyingType<T, U>, T>::value, "!"); 66 } 67 68 UnderlyingType & operator=(const UnderlyingType &) = delete; 69 UnderlyingType & operator=(UnderlyingType &&) = delete; 70 71 /** 72 * @brief Creates a new resource of the given type. 73 * @param args Arguments to be forwarded to the actual constructor (if any). 74 * @return A pointer to the newly created resource. 75 */ 76 template<typename... Args> create(Args &&...args)77 static std::shared_ptr<T> create(Args&&... args) { 78 return std::make_shared<T>(ConstructorAccess{0}, std::forward<Args>(args)...); 79 } 80 81 /** 82 * @brief Gets the loop from which the resource was originated. 83 * @return A reference to a loop instance. 84 */ loop() const85 Loop & loop() const noexcept { return *pLoop; } 86 87 /** 88 * @brief Gets the underlying raw data structure. 89 * 90 * This function should not be used, unless you know exactly what you are 91 * doing and what are the risks.<br/> 92 * Going raw is dangerous, mainly because the lifetime management of a loop, 93 * a handle or a request is in charge to the library itself and users should 94 * not work around it. 95 * 96 * @warning 97 * Use this function at your own risk, but do not expect any support in case 98 * of bugs. 99 * 100 * @return The underlying raw data structure. 101 */ raw() const102 const U * raw() const noexcept { 103 return &resource; 104 } 105 106 /** 107 * @brief Gets the underlying raw data structure. 108 * 109 * This function should not be used, unless you know exactly what you are 110 * doing and what are the risks.<br/> 111 * Going raw is dangerous, mainly because the lifetime management of a loop, 112 * a handle or a request is in charge to the library itself and users should 113 * not work around it. 114 * 115 * @warning 116 * Use this function at your own risk, but do not expect any support in case 117 * of bugs. 118 * 119 * @return The underlying raw data structure. 120 */ raw()121 U * raw() noexcept { 122 return const_cast<U *>(const_cast<const UnderlyingType *>(this)->raw()); 123 } 124 125 private: 126 std::shared_ptr<Loop> pLoop; 127 U resource; 128 }; 129 130 131 } 132