annotate win64-msvc/include/kj/memory.h @ 73:02caadb7509e

Rebuild with --disable-stack-protector for mingw32
author Chris Cannam
date Fri, 25 Jan 2019 14:31:07 +0000
parents 0f2d93caa50c
children
rev   line source
Chris@63 1 // Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors
Chris@63 2 // Licensed under the MIT License:
Chris@63 3 //
Chris@63 4 // Permission is hereby granted, free of charge, to any person obtaining a copy
Chris@63 5 // of this software and associated documentation files (the "Software"), to deal
Chris@63 6 // in the Software without restriction, including without limitation the rights
Chris@63 7 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
Chris@63 8 // copies of the Software, and to permit persons to whom the Software is
Chris@63 9 // furnished to do so, subject to the following conditions:
Chris@63 10 //
Chris@63 11 // The above copyright notice and this permission notice shall be included in
Chris@63 12 // all copies or substantial portions of the Software.
Chris@63 13 //
Chris@63 14 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
Chris@63 15 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
Chris@63 16 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
Chris@63 17 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
Chris@63 18 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
Chris@63 19 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
Chris@63 20 // THE SOFTWARE.
Chris@63 21
Chris@63 22 #ifndef KJ_MEMORY_H_
Chris@63 23 #define KJ_MEMORY_H_
Chris@63 24
Chris@63 25 #if defined(__GNUC__) && !KJ_HEADER_WARNINGS
Chris@63 26 #pragma GCC system_header
Chris@63 27 #endif
Chris@63 28
Chris@63 29 #include "common.h"
Chris@63 30
Chris@63 31 namespace kj {
Chris@63 32
Chris@63 33 // =======================================================================================
Chris@63 34 // Disposer -- Implementation details.
Chris@63 35
Chris@63 36 class Disposer {
Chris@63 37 // Abstract interface for a thing that "disposes" of objects, where "disposing" usually means
Chris@63 38 // calling the destructor followed by freeing the underlying memory. `Own<T>` encapsulates an
Chris@63 39 // object pointer with corresponding Disposer.
Chris@63 40 //
Chris@63 41 // Few developers will ever touch this interface. It is primarily useful for those implementing
Chris@63 42 // custom memory allocators.
Chris@63 43
Chris@63 44 protected:
Chris@63 45 // Do not declare a destructor, as doing so will force a global initializer for each HeapDisposer
Chris@63 46 // instance. Eww!
Chris@63 47
Chris@63 48 virtual void disposeImpl(void* pointer) const = 0;
Chris@63 49 // Disposes of the object, given a pointer to the beginning of the object. If the object is
Chris@63 50 // polymorphic, this pointer is determined by dynamic_cast<void*>(). For non-polymorphic types,
Chris@63 51 // Own<T> does not allow any casting, so the pointer exactly matches the original one given to
Chris@63 52 // Own<T>.
Chris@63 53
Chris@63 54 public:
Chris@63 55
Chris@63 56 template <typename T>
Chris@63 57 void dispose(T* object) const;
Chris@63 58 // Helper wrapper around disposeImpl().
Chris@63 59 //
Chris@63 60 // If T is polymorphic, calls `disposeImpl(dynamic_cast<void*>(object))`, otherwise calls
Chris@63 61 // `disposeImpl(implicitCast<void*>(object))`.
Chris@63 62 //
Chris@63 63 // Callers must not call dispose() on the same pointer twice, even if the first call throws
Chris@63 64 // an exception.
Chris@63 65
Chris@63 66 private:
Chris@63 67 template <typename T, bool polymorphic = __is_polymorphic(T)>
Chris@63 68 struct Dispose_;
Chris@63 69 };
Chris@63 70
Chris@63 71 template <typename T>
Chris@63 72 class DestructorOnlyDisposer: public Disposer {
Chris@63 73 // A disposer that merely calls the type's destructor and nothing else.
Chris@63 74
Chris@63 75 public:
Chris@63 76 static const DestructorOnlyDisposer instance;
Chris@63 77
Chris@63 78 void disposeImpl(void* pointer) const override {
Chris@63 79 reinterpret_cast<T*>(pointer)->~T();
Chris@63 80 }
Chris@63 81 };
Chris@63 82
Chris@63 83 template <typename T>
Chris@63 84 const DestructorOnlyDisposer<T> DestructorOnlyDisposer<T>::instance = DestructorOnlyDisposer<T>();
Chris@63 85
Chris@63 86 class NullDisposer: public Disposer {
Chris@63 87 // A disposer that does nothing.
Chris@63 88
Chris@63 89 public:
Chris@63 90 static const NullDisposer instance;
Chris@63 91
Chris@63 92 void disposeImpl(void* pointer) const override {}
Chris@63 93 };
Chris@63 94
Chris@63 95 // =======================================================================================
Chris@63 96 // Own<T> -- An owned pointer.
Chris@63 97
Chris@63 98 template <typename T>
Chris@63 99 class Own {
Chris@63 100 // A transferrable title to a T. When an Own<T> goes out of scope, the object's Disposer is
Chris@63 101 // called to dispose of it. An Own<T> can be efficiently passed by move, without relocating the
Chris@63 102 // underlying object; this transfers ownership.
Chris@63 103 //
Chris@63 104 // This is much like std::unique_ptr, except:
Chris@63 105 // - You cannot release(). An owned object is not necessarily allocated with new (see next
Chris@63 106 // point), so it would be hard to use release() correctly.
Chris@63 107 // - The deleter is made polymorphic by virtual call rather than by template. This is much
Chris@63 108 // more powerful -- it allows the use of custom allocators, freelists, etc. This could
Chris@63 109 // _almost_ be accomplished with unique_ptr by forcing everyone to use something like
Chris@63 110 // std::unique_ptr<T, kj::Deleter>, except that things get hairy in the presence of multiple
Chris@63 111 // inheritance and upcasting, and anyway if you force everyone to use a custom deleter
Chris@63 112 // then you've lost any benefit to interoperating with the "standard" unique_ptr.
Chris@63 113
Chris@63 114 public:
Chris@63 115 KJ_DISALLOW_COPY(Own);
Chris@63 116 inline Own(): disposer(nullptr), ptr(nullptr) {}
Chris@63 117 inline Own(Own&& other) noexcept
Chris@63 118 : disposer(other.disposer), ptr(other.ptr) { other.ptr = nullptr; }
Chris@63 119 inline Own(Own<RemoveConstOrDisable<T>>&& other) noexcept
Chris@63 120 : disposer(other.disposer), ptr(other.ptr) { other.ptr = nullptr; }
Chris@63 121 template <typename U, typename = EnableIf<canConvert<U*, T*>()>>
Chris@63 122 inline Own(Own<U>&& other) noexcept
Chris@63 123 : disposer(other.disposer), ptr(other.ptr) {
Chris@63 124 static_assert(__is_polymorphic(T),
Chris@63 125 "Casting owned pointers requires that the target type is polymorphic.");
Chris@63 126 other.ptr = nullptr;
Chris@63 127 }
Chris@63 128 inline Own(T* ptr, const Disposer& disposer) noexcept: disposer(&disposer), ptr(ptr) {}
Chris@63 129
Chris@63 130 ~Own() noexcept(false) { dispose(); }
Chris@63 131
Chris@63 132 inline Own& operator=(Own&& other) {
Chris@63 133 // Move-assingnment operator.
Chris@63 134
Chris@63 135 // Careful, this might own `other`. Therefore we have to transfer the pointers first, then
Chris@63 136 // dispose.
Chris@63 137 const Disposer* disposerCopy = disposer;
Chris@63 138 T* ptrCopy = ptr;
Chris@63 139 disposer = other.disposer;
Chris@63 140 ptr = other.ptr;
Chris@63 141 other.ptr = nullptr;
Chris@63 142 if (ptrCopy != nullptr) {
Chris@63 143 disposerCopy->dispose(const_cast<RemoveConst<T>*>(ptrCopy));
Chris@63 144 }
Chris@63 145 return *this;
Chris@63 146 }
Chris@63 147
Chris@63 148 inline Own& operator=(decltype(nullptr)) {
Chris@63 149 dispose();
Chris@63 150 return *this;
Chris@63 151 }
Chris@63 152
Chris@63 153 template <typename U>
Chris@63 154 Own<U> downcast() {
Chris@63 155 // Downcast the pointer to Own<U>, destroying the original pointer. If this pointer does not
Chris@63 156 // actually point at an instance of U, the results are undefined (throws an exception in debug
Chris@63 157 // mode if RTTI is enabled, otherwise you're on your own).
Chris@63 158
Chris@63 159 Own<U> result;
Chris@63 160 if (ptr != nullptr) {
Chris@63 161 result.ptr = &kj::downcast<U>(*ptr);
Chris@63 162 result.disposer = disposer;
Chris@63 163 ptr = nullptr;
Chris@63 164 }
Chris@63 165 return result;
Chris@63 166 }
Chris@63 167
Chris@63 168 #define NULLCHECK KJ_IREQUIRE(ptr != nullptr, "null Own<> dereference")
Chris@63 169 inline T* operator->() { NULLCHECK; return ptr; }
Chris@63 170 inline const T* operator->() const { NULLCHECK; return ptr; }
Chris@63 171 inline T& operator*() { NULLCHECK; return *ptr; }
Chris@63 172 inline const T& operator*() const { NULLCHECK; return *ptr; }
Chris@63 173 #undef NULLCHECK
Chris@63 174 inline T* get() { return ptr; }
Chris@63 175 inline const T* get() const { return ptr; }
Chris@63 176 inline operator T*() { return ptr; }
Chris@63 177 inline operator const T*() const { return ptr; }
Chris@63 178
Chris@63 179 private:
Chris@63 180 const Disposer* disposer; // Only valid if ptr != nullptr.
Chris@63 181 T* ptr;
Chris@63 182
Chris@63 183 inline explicit Own(decltype(nullptr)): disposer(nullptr), ptr(nullptr) {}
Chris@63 184
Chris@63 185 inline bool operator==(decltype(nullptr)) { return ptr == nullptr; }
Chris@63 186 inline bool operator!=(decltype(nullptr)) { return ptr != nullptr; }
Chris@63 187 // Only called by Maybe<Own<T>>.
Chris@63 188
Chris@63 189 inline void dispose() {
Chris@63 190 // Make sure that if an exception is thrown, we are left with a null ptr, so we won't possibly
Chris@63 191 // dispose again.
Chris@63 192 T* ptrCopy = ptr;
Chris@63 193 if (ptrCopy != nullptr) {
Chris@63 194 ptr = nullptr;
Chris@63 195 disposer->dispose(const_cast<RemoveConst<T>*>(ptrCopy));
Chris@63 196 }
Chris@63 197 }
Chris@63 198
Chris@63 199 template <typename U>
Chris@63 200 friend class Own;
Chris@63 201 friend class Maybe<Own<T>>;
Chris@63 202 };
Chris@63 203
Chris@63 204 namespace _ { // private
Chris@63 205
Chris@63 206 template <typename T>
Chris@63 207 class OwnOwn {
Chris@63 208 public:
Chris@63 209 inline OwnOwn(Own<T>&& value) noexcept: value(kj::mv(value)) {}
Chris@63 210
Chris@63 211 inline Own<T>& operator*() & { return value; }
Chris@63 212 inline const Own<T>& operator*() const & { return value; }
Chris@63 213 inline Own<T>&& operator*() && { return kj::mv(value); }
Chris@63 214 inline const Own<T>&& operator*() const && { return kj::mv(value); }
Chris@63 215 inline Own<T>* operator->() { return &value; }
Chris@63 216 inline const Own<T>* operator->() const { return &value; }
Chris@63 217 inline operator Own<T>*() { return value ? &value : nullptr; }
Chris@63 218 inline operator const Own<T>*() const { return value ? &value : nullptr; }
Chris@63 219
Chris@63 220 private:
Chris@63 221 Own<T> value;
Chris@63 222 };
Chris@63 223
Chris@63 224 template <typename T>
Chris@63 225 OwnOwn<T> readMaybe(Maybe<Own<T>>&& maybe) { return OwnOwn<T>(kj::mv(maybe.ptr)); }
Chris@63 226 template <typename T>
Chris@63 227 Own<T>* readMaybe(Maybe<Own<T>>& maybe) { return maybe.ptr ? &maybe.ptr : nullptr; }
Chris@63 228 template <typename T>
Chris@63 229 const Own<T>* readMaybe(const Maybe<Own<T>>& maybe) { return maybe.ptr ? &maybe.ptr : nullptr; }
Chris@63 230
Chris@63 231 } // namespace _ (private)
Chris@63 232
Chris@63 233 template <typename T>
Chris@63 234 class Maybe<Own<T>> {
Chris@63 235 public:
Chris@63 236 inline Maybe(): ptr(nullptr) {}
Chris@63 237 inline Maybe(Own<T>&& t) noexcept: ptr(kj::mv(t)) {}
Chris@63 238 inline Maybe(Maybe&& other) noexcept: ptr(kj::mv(other.ptr)) {}
Chris@63 239
Chris@63 240 template <typename U>
Chris@63 241 inline Maybe(Maybe<Own<U>>&& other): ptr(mv(other.ptr)) {}
Chris@63 242 template <typename U>
Chris@63 243 inline Maybe(Own<U>&& other): ptr(mv(other)) {}
Chris@63 244
Chris@63 245 inline Maybe(decltype(nullptr)) noexcept: ptr(nullptr) {}
Chris@63 246
Chris@63 247 inline operator Maybe<T&>() { return ptr.get(); }
Chris@63 248 inline operator Maybe<const T&>() const { return ptr.get(); }
Chris@63 249
Chris@63 250 inline Maybe& operator=(Maybe&& other) { ptr = kj::mv(other.ptr); return *this; }
Chris@63 251
Chris@63 252 inline bool operator==(decltype(nullptr)) const { return ptr == nullptr; }
Chris@63 253 inline bool operator!=(decltype(nullptr)) const { return ptr != nullptr; }
Chris@63 254
Chris@63 255 Own<T>& orDefault(Own<T>& defaultValue) {
Chris@63 256 if (ptr == nullptr) {
Chris@63 257 return defaultValue;
Chris@63 258 } else {
Chris@63 259 return ptr;
Chris@63 260 }
Chris@63 261 }
Chris@63 262 const Own<T>& orDefault(const Own<T>& defaultValue) const {
Chris@63 263 if (ptr == nullptr) {
Chris@63 264 return defaultValue;
Chris@63 265 } else {
Chris@63 266 return ptr;
Chris@63 267 }
Chris@63 268 }
Chris@63 269
Chris@63 270 template <typename Func>
Chris@63 271 auto map(Func&& f) & -> Maybe<decltype(f(instance<Own<T>&>()))> {
Chris@63 272 if (ptr == nullptr) {
Chris@63 273 return nullptr;
Chris@63 274 } else {
Chris@63 275 return f(ptr);
Chris@63 276 }
Chris@63 277 }
Chris@63 278
Chris@63 279 template <typename Func>
Chris@63 280 auto map(Func&& f) const & -> Maybe<decltype(f(instance<const Own<T>&>()))> {
Chris@63 281 if (ptr == nullptr) {
Chris@63 282 return nullptr;
Chris@63 283 } else {
Chris@63 284 return f(ptr);
Chris@63 285 }
Chris@63 286 }
Chris@63 287
Chris@63 288 template <typename Func>
Chris@63 289 auto map(Func&& f) && -> Maybe<decltype(f(instance<Own<T>&&>()))> {
Chris@63 290 if (ptr == nullptr) {
Chris@63 291 return nullptr;
Chris@63 292 } else {
Chris@63 293 return f(kj::mv(ptr));
Chris@63 294 }
Chris@63 295 }
Chris@63 296
Chris@63 297 template <typename Func>
Chris@63 298 auto map(Func&& f) const && -> Maybe<decltype(f(instance<const Own<T>&&>()))> {
Chris@63 299 if (ptr == nullptr) {
Chris@63 300 return nullptr;
Chris@63 301 } else {
Chris@63 302 return f(kj::mv(ptr));
Chris@63 303 }
Chris@63 304 }
Chris@63 305
Chris@63 306 private:
Chris@63 307 Own<T> ptr;
Chris@63 308
Chris@63 309 template <typename U>
Chris@63 310 friend class Maybe;
Chris@63 311 template <typename U>
Chris@63 312 friend _::OwnOwn<U> _::readMaybe(Maybe<Own<U>>&& maybe);
Chris@63 313 template <typename U>
Chris@63 314 friend Own<U>* _::readMaybe(Maybe<Own<U>>& maybe);
Chris@63 315 template <typename U>
Chris@63 316 friend const Own<U>* _::readMaybe(const Maybe<Own<U>>& maybe);
Chris@63 317 };
Chris@63 318
Chris@63 319 namespace _ { // private
Chris@63 320
Chris@63 321 template <typename T>
Chris@63 322 class HeapDisposer final: public Disposer {
Chris@63 323 public:
Chris@63 324 virtual void disposeImpl(void* pointer) const override { delete reinterpret_cast<T*>(pointer); }
Chris@63 325
Chris@63 326 static const HeapDisposer instance;
Chris@63 327 };
Chris@63 328
Chris@63 329 template <typename T>
Chris@63 330 const HeapDisposer<T> HeapDisposer<T>::instance = HeapDisposer<T>();
Chris@63 331
Chris@63 332 } // namespace _ (private)
Chris@63 333
Chris@63 334 template <typename T, typename... Params>
Chris@63 335 Own<T> heap(Params&&... params) {
Chris@63 336 // heap<T>(...) allocates a T on the heap, forwarding the parameters to its constructor. The
Chris@63 337 // exact heap implementation is unspecified -- for now it is operator new, but you should not
Chris@63 338 // assume this. (Since we know the object size at delete time, we could actually implement an
Chris@63 339 // allocator that is more efficient than operator new.)
Chris@63 340
Chris@63 341 return Own<T>(new T(kj::fwd<Params>(params)...), _::HeapDisposer<T>::instance);
Chris@63 342 }
Chris@63 343
Chris@63 344 template <typename T>
Chris@63 345 Own<Decay<T>> heap(T&& orig) {
Chris@63 346 // Allocate a copy (or move) of the argument on the heap.
Chris@63 347 //
Chris@63 348 // The purpose of this overload is to allow you to omit the template parameter as there is only
Chris@63 349 // one argument and the purpose is to copy it.
Chris@63 350
Chris@63 351 typedef Decay<T> T2;
Chris@63 352 return Own<T2>(new T2(kj::fwd<T>(orig)), _::HeapDisposer<T2>::instance);
Chris@63 353 }
Chris@63 354
Chris@63 355 // =======================================================================================
Chris@63 356 // SpaceFor<T> -- assists in manual allocation
Chris@63 357
Chris@63 358 template <typename T>
Chris@63 359 class SpaceFor {
Chris@63 360 // A class which has the same size and alignment as T but does not call its constructor or
Chris@63 361 // destructor automatically. Instead, call construct() to construct a T in the space, which
Chris@63 362 // returns an Own<T> which will take care of calling T's destructor later.
Chris@63 363
Chris@63 364 public:
Chris@63 365 inline SpaceFor() {}
Chris@63 366 inline ~SpaceFor() {}
Chris@63 367
Chris@63 368 template <typename... Params>
Chris@63 369 Own<T> construct(Params&&... params) {
Chris@63 370 ctor(value, kj::fwd<Params>(params)...);
Chris@63 371 return Own<T>(&value, DestructorOnlyDisposer<T>::instance);
Chris@63 372 }
Chris@63 373
Chris@63 374 private:
Chris@63 375 union {
Chris@63 376 T value;
Chris@63 377 };
Chris@63 378 };
Chris@63 379
Chris@63 380 // =======================================================================================
Chris@63 381 // Inline implementation details
Chris@63 382
Chris@63 383 template <typename T>
Chris@63 384 struct Disposer::Dispose_<T, true> {
Chris@63 385 static void dispose(T* object, const Disposer& disposer) {
Chris@63 386 // Note that dynamic_cast<void*> does not require RTTI to be enabled, because the offset to
Chris@63 387 // the top of the object is in the vtable -- as it obviously needs to be to correctly implement
Chris@63 388 // operator delete.
Chris@63 389 disposer.disposeImpl(dynamic_cast<void*>(object));
Chris@63 390 }
Chris@63 391 };
Chris@63 392 template <typename T>
Chris@63 393 struct Disposer::Dispose_<T, false> {
Chris@63 394 static void dispose(T* object, const Disposer& disposer) {
Chris@63 395 disposer.disposeImpl(static_cast<void*>(object));
Chris@63 396 }
Chris@63 397 };
Chris@63 398
Chris@63 399 template <typename T>
Chris@63 400 void Disposer::dispose(T* object) const {
Chris@63 401 Dispose_<T>::dispose(object, *this);
Chris@63 402 }
Chris@63 403
Chris@63 404 } // namespace kj
Chris@63 405
Chris@63 406 #endif // KJ_MEMORY_H_