1 /**************************************************************************** 2 ** 3 ** DQt - D bindings for the Qt Toolkit 4 ** 5 ** GNU Lesser General Public License Usage 6 ** This file may be used under the terms of the GNU Lesser 7 ** General Public License version 3 as published by the Free Software 8 ** Foundation and appearing in the file LICENSE.LGPL3 included in the 9 ** packaging of this file. Please review the following information to 10 ** ensure the GNU Lesser General Public License version 3 requirements 11 ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. 12 ** 13 ****************************************************************************/ 14 module qt.core.shareddata; 15 extern(C++): 16 17 import qt.config; 18 import qt.core.atomic; 19 import qt.helpers; 20 21 /+ #if QT_DEPRECATED_SINCE(5, 6) 22 #endif 23 24 25 template <class T> class QSharedDataPointer; +/ 26 27 extern(C++, class) struct 28 /+ #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) 29 Q_CORE_EXPORT 30 #endif +/ 31 QSharedData 32 { 33 public: 34 /+ mutable +/ QAtomicInt ref_/* = 0*/; 35 36 @disable this(); 37 /+pragma(inline, true) this()/+ noexcept+/ 38 { 39 this.ref_ = 0; 40 }+/ 41 @disable this(this); 42 pragma(inline, true) this(ref const(QSharedData) )/+ noexcept+/ 43 { 44 this.ref_ = 0; 45 } 46 47 // using the assignment operator would lead to corruption in the ref-counting 48 /+ref QSharedData operator =(ref const(QSharedData) ) /+ = delete +/;+/ 49 /+ ~QSharedData() = default; +/ 50 } 51 52 extern(C++, class) struct QSharedDataPointer(T) 53 { 54 public: 55 alias Type = T; 56 alias pointer = T*; 57 58 pragma(inline, true) void detach()() { if (d && d.ref_.loadRelaxed() != 1) detach_helper(); } 59 pragma(inline, true) ref T opUnary(string op)() if(op == "*") { detach(); return *d; } 60 pragma(inline, true) ref const(T) opUnary(string op)() const if(op == "*") { return *d; } 61 /+pragma(inline, true) T* operator ->() { detach(); return d; }+/ 62 /+pragma(inline, true) const(T)* operator ->() const { return d; }+/ 63 /+pragma(inline, true) auto opCast(T : T)() { detach(); return d; }+/ 64 /+pragma(inline, true) auto opCast(T : const(T))() const { return d; }+/ 65 pragma(inline, true) T* data()() { detach(); return d; } 66 pragma(inline, true) const(T)* data()() const { return d; } 67 pragma(inline, true) const(T)* constData() const { return d; } 68 69 /+pragma(inline, true) bool operator ==(ref const(QSharedDataPointer!(T)) other) const { return d == other.d; }+/ 70 /+pragma(inline, true) bool operator !=(ref const(QSharedDataPointer!(T)) other) const { return d != other.d; }+/ 71 72 /+pragma(inline, true) this() { d = null; }+/ 73 pragma(inline, true) ~this() { 74 import core.stdcpp.new_; 75 static if(__traits(compiles, (*d).sizeof)) 76 { 77 import core.stdcpp.new_; 78 if (d && !d.ref_.deref()) cpp_delete(d); 79 } 80 else 81 assert(false); 82 } 83 84 /+ /+ explicit +/pragma(inline, true) this(T* adata)/+ noexcept+/ 85 { 86 this.d = adata; 87 if (d) d.ref_.ref_(); 88 }+/ 89 @disable this(this); 90 pragma(inline, true) this(ref const(QSharedDataPointer!(T)) o) 91 { 92 this.d = cast(T*)o.d; 93 static if(__traits(compiles, d.ref_)) 94 { 95 if (d) d.ref_.ref_(); 96 } 97 else 98 assert(0); 99 } 100 /+pragma(inline, true) ref QSharedDataPointer!(T) operator =(ref const(QSharedDataPointer!(T)) o) { 101 import core.stdcpp.new_; 102 103 if (o.d != d) { 104 if (o.d) 105 o.d.ref_.ref_(); 106 T* old = d; 107 d = o.d; 108 if (old && !old.ref_.deref()) 109 cpp_delete(old); 110 } 111 return this; 112 }+/ 113 /+pragma(inline, true) ref QSharedDataPointer operator =(T* o) { 114 import core.stdcpp.new_; 115 116 if (o != d) { 117 if (o) 118 o.ref_.ref_(); 119 T* old = d; 120 d = o; 121 if (old && !old.ref_.deref()) 122 cpp_delete(old); 123 } 124 return this; 125 }+/ 126 /+ QSharedDataPointer(QSharedDataPointer &&o) noexcept : d(o.d) { o.d = nullptr; } +/ 127 /+ inline QSharedDataPointer<T> &operator=(QSharedDataPointer<T> &&other) noexcept 128 { 129 QSharedDataPointer moved(std::move(other)); 130 swap(moved); 131 return *this; 132 } +/ 133 134 /+pragma(inline, true) bool operator !() const { return !d; }+/ 135 136 /+ inline void swap(QSharedDataPointer &other) noexcept 137 { qSwap(d, other.d); } +/ 138 139 protected: 140 pragma(inline, true) T* clone()() 141 { 142 import core.stdcpp.new_; 143 144 return cpp_new!T(*d); 145 } 146 147 private: 148 void detach_helper()() 149 { 150 import core.stdcpp.new_; 151 152 T* x = clone(); 153 x.ref_.ref_(); 154 if (!d.ref_.deref()) 155 cpp_delete(d); 156 d = x; 157 } 158 159 T* d; 160 } 161 162 /+pragma(inline, true) bool operator ==(T)(/+ std:: +/nullptr_t p1, ref const(QSharedDataPointer!(T)) p2) 163 { 164 /+ Q_UNUSED(p1) +/ 165 return !p2; 166 }+/ 167 168 /+pragma(inline, true) bool operator ==(T)(ref const(QSharedDataPointer!(T)) p1, /+ std:: +/nullptr_t p2) 169 { 170 /+ Q_UNUSED(p2) +/ 171 return !p1; 172 }+/ 173 174 extern(C++, class) struct QExplicitlySharedDataPointer(T) 175 { 176 public: 177 alias Type = T; 178 alias pointer = T*; 179 180 pragma(inline, true) ref T opUnary(string op)() const if(op == "*") { return *d; } 181 /+pragma(inline, true) T* operator ->() { return d; }+/ 182 /+pragma(inline, true) T* operator ->() const { return d; }+/ 183 pragma(inline, true) T* data() const { return cast(T*)d; } 184 pragma(inline, true) const(T)* constData() const { return d; } 185 pragma(inline, true) T* take() { T* x = d; d = null; return x; } 186 187 pragma(inline, true) void detach()() { if (d && d.ref_.loadRelaxed() != 1) detach_helper(); } 188 189 pragma(inline, true) void reset()() 190 { 191 import core.stdcpp.new_; 192 193 if(d && !d.ref_.deref()) 194 cpp_delete(d); 195 196 d = null; 197 } 198 199 /+pragma(inline, true) auto opCast(T : bool) () const { return d !is null; }+/ 200 201 /+pragma(inline, true) bool operator ==(ref const(QExplicitlySharedDataPointer!(T)) other) const { return d == other.d; }+/ 202 /+pragma(inline, true) bool operator !=(ref const(QExplicitlySharedDataPointer!(T)) other) const { return d != other.d; }+/ 203 /+pragma(inline, true) bool operator ==(const(T)* ptr) const { return d == ptr; }+/ 204 /+pragma(inline, true) bool operator !=(const(T)* ptr) const { return d != ptr; }+/ 205 206 /+pragma(inline, true) this() { d = null; }+/ 207 pragma(inline, true) ~this() { 208 static if(__traits(compiles, (*d).sizeof)) 209 { 210 import core.stdcpp.new_; 211 if (d && !d.ref_.deref()) cpp_delete(d); 212 } 213 else 214 assert(false); 215 } 216 217 /+ /+ explicit +/pragma(inline, true) this(T* adata)/+ noexcept+/ 218 { 219 this.d = adata; 220 if (d) d.ref_.ref_(); 221 }+/ 222 @disable this(this); 223 pragma(inline, true) this(ref const(QExplicitlySharedDataPointer!(T)) o) 224 { 225 static if(__traits(compiles, (*d).sizeof)) 226 { 227 this.d = cast(T*)o.d; 228 if (d) d.ref_.ref_(); 229 } 230 else 231 assert(false); 232 } 233 234 /+ template<class X> +/ 235 /+ inline QExplicitlySharedDataPointer(const QExplicitlySharedDataPointer<X> &o) 236 #ifdef QT_ENABLE_QEXPLICITLYSHAREDDATAPOINTER_STATICCAST 237 : d(static_cast<T *>(o.data())) 238 #else 239 : d(o.data()) 240 #endif 241 { 242 if(d) 243 d->ref.ref(); 244 } +/ 245 246 /+pragma(inline, true) ref QExplicitlySharedDataPointer!(T) operator =(ref const(QExplicitlySharedDataPointer!(T)) o) { 247 import core.stdcpp.new_; 248 249 if (o.d != d) { 250 if (o.d) 251 o.d.ref_.ref_(); 252 T* old = d; 253 d = o.d; 254 if (old && !old.ref_.deref()) 255 cpp_delete(old); 256 } 257 return this; 258 }+/ 259 /+pragma(inline, true) ref QExplicitlySharedDataPointer operator =(T* o) { 260 import core.stdcpp.new_; 261 262 if (o != d) { 263 if (o) 264 o.ref_.ref_(); 265 T* old = d; 266 d = o; 267 if (old && !old.ref_.deref()) 268 cpp_delete(old); 269 } 270 return this; 271 }+/ 272 /+ inline QExplicitlySharedDataPointer(QExplicitlySharedDataPointer &&o) noexcept : d(o.d) { o.d = nullptr; } +/ 273 /+ inline QExplicitlySharedDataPointer<T> &operator=(QExplicitlySharedDataPointer<T> &&other) noexcept 274 { 275 QExplicitlySharedDataPointer moved(std::move(other)); 276 swap(moved); 277 return *this; 278 } +/ 279 280 /+pragma(inline, true) bool operator !() const { return !d; }+/ 281 282 /+ inline void swap(QExplicitlySharedDataPointer &other) noexcept 283 { qSwap(d, other.d); } +/ 284 285 protected: 286 pragma(inline, true) T* clone()() 287 { 288 import core.stdcpp.new_; 289 290 return cpp_new!T(*d); 291 } 292 293 private: 294 void detach_helper()() 295 { 296 import core.stdcpp.new_; 297 298 T* x = clone(); 299 x.ref_.ref_(); 300 if (!d.ref_.deref()) 301 cpp_delete(d); 302 d = x; 303 } 304 305 T* d; 306 } 307 308 /+pragma(inline, true) bool operator ==(T)(/+ std:: +/nullptr_t p1, ref const(QExplicitlySharedDataPointer!(T)) p2) 309 { 310 /+ Q_UNUSED(p1) +/ 311 return !p2; 312 }+/ 313 314 /+pragma(inline, true) bool operator ==(T)(ref const(QExplicitlySharedDataPointer!(T)) p1, /+ std:: +/nullptr_t p2) 315 { 316 /+ Q_UNUSED(p2) +/ 317 return !p1; 318 }+/ 319 320 /+ template <class T> 321 void swap(QSharedDataPointer<T> &p1, QSharedDataPointer<T> &p2) 322 { p1.swap(p2); } 323 324 template <class T> 325 void swap(QExplicitlySharedDataPointer<T> &p1, QExplicitlySharedDataPointer<T> &p2) 326 { p1.swap(p2); } 327 328 template <class T> 329 uint qHash(const QSharedDataPointer<T> &ptr, uint seed = 0) noexcept 330 { 331 return qHash(ptr.data(), seed); 332 } 333 template <class T> 334 uint qHash(const QExplicitlySharedDataPointer<T> &ptr, uint seed = 0) noexcept 335 { 336 return qHash(ptr.data(), seed); 337 } 338 339 template<typename T> Q_DECLARE_TYPEINFO_BODY(QSharedDataPointer<T>, Q_MOVABLE_TYPE); 340 template<typename T> Q_DECLARE_TYPEINFO_BODY(QExplicitlySharedDataPointer<T>, Q_MOVABLE_TYPE); +/ 341