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