annotate win32-mingw/include/kj/memory.h @ 62:0994c39f1e94

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