memory.hpp (3478B)
1 // Copyright (c) 2020 Morel BĂ©renger 2 // 3 // This software is provided 'as-is', without any express or implied 4 // warranty. In no event will the authors be held liable for any damages 5 // arising from the use of this software. 6 // 7 // Permission is granted to anyone to use this software for any purpose, 8 // including commercial applications, and to alter it and redistribute it 9 // freely, subject to the following restrictions: 10 // 11 // 1. The origin of this software must not be misrepresented; you must not 12 // claim that you wrote the original software. If you use this software 13 // in a product, an acknowledgment in the product documentation would be 14 // appreciated but is not required. 15 // 2. Altered source versions must be plainly marked as such, and must not be 16 // misrepresented as being the original software. 17 // 3. This notice may not be removed or altered from any source distribution. 18 19 // This file defines unique_res and weak_res class utilities. 20 // goal: easy RAII for any resource, without any assumption 21 // about what is an invalid value, and without consuming 22 // more data memory than a single, raw pointer. 23 24 #ifndef MEMORY_HPP 25 #define MEMORY_HPP 26 27 #include <utility> 28 29 // ease the life for memory stuff, just use: 30 // typedef unique_res<T,nullptr,generic_free<T>> T_owner; 31 // typedef weak_res<T,nullptr> T_owned; 32 template <typename T> 33 void generic_free( T* p ) 34 { 35 delete p; 36 } 37 38 // those classes are purely for semantics, and do not 39 // provide any real guarantee, as anyone is free to call 40 // `close()`, `free()` or whatever function able to release 41 // resource in `T`, but at least it should make it easier to 42 // understand that it is a bad idea. 43 // Arrays are explicitly not handled, because that's what 44 // vector is for. If you can't affort the small overhead of 45 // one pointer per collection, you likely can afford to 46 // write your own stuff. 47 48 template 49 < 50 typename T, 51 T INVALID_VAL 52 > 53 class weak_res 54 { 55 protected: 56 typedef weak_res<T,INVALID_VAL> COMPLETE_TYPE; 57 T m_data; 58 public: 59 bool valid( void ) const 60 { 61 return m_data != INVALID_VAL; 62 } 63 64 bool operator==( COMPLETE_TYPE const& other ) const 65 { 66 return m_data == other.m_data; 67 } 68 69 bool operator==( T const& other ) const 70 { 71 return m_data == other; 72 } 73 74 bool operator!=( COMPLETE_TYPE const& other ) const 75 { 76 return m_data != other.m_data; 77 } 78 79 bool operator!=( T const& other ) const 80 { 81 return m_data != other; 82 } 83 84 const T get( void ) const 85 { 86 return m_data; 87 } 88 }; 89 90 template 91 < 92 typename T, 93 T INVALID_VAL, 94 void(*DTOR)(T) 95 > 96 class unique_res : public weak_res<T,INVALID_VAL> 97 { 98 typedef unique_res<T,INVALID_VAL,DTOR> UNIQUE_TYPE; 99 public: 100 unique_res( UNIQUE_TYPE const& ) = delete; 101 UNIQUE_TYPE& operator=( UNIQUE_TYPE const& other ) = delete; 102 103 unique_res( void ) 104 { 105 this->m_data = INVALID_VAL; 106 } 107 108 unique_res( UNIQUE_TYPE && other ) 109 { 110 this->m_data = other.m_data; 111 other.m_data = INVALID_VAL; 112 } 113 114 unique_res( T && src ) 115 { 116 this->m_data = src; 117 src = INVALID_VAL; 118 } 119 120 UNIQUE_TYPE& operator=( UNIQUE_TYPE && other ) 121 { 122 clear(); 123 std::swap( this->m_data, other.m_data ); 124 return *this; 125 } 126 127 UNIQUE_TYPE& operator=( T && other ) 128 { 129 clear(); 130 std::swap( this->m_data, other ); 131 return *this; 132 } 133 134 T release( void ) 135 { 136 T ret = this->m_data; 137 this->m_data = INVALID_VAL; 138 return ret; 139 } 140 141 void clear( void ) 142 { 143 if( INVALID_VAL != this->m_data ) 144 { 145 DTOR( this->m_data ); 146 this->m_data = INVALID_VAL; 147 } 148 } 149 150 ~unique_res( void ) 151 { 152 clear(); 153 } 154 }; 155 156 #endif