mfbt/Maybe.h

Tue, 06 Jan 2015 21:39:09 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Tue, 06 Jan 2015 21:39:09 +0100
branch
TOR_BUG_9701
changeset 8
97036ab72558
permissions
-rw-r--r--

Conditionally force memory storage according to privacy.thirdparty.isolate;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.

     1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
     2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
     3 /* This Source Code Form is subject to the terms of the Mozilla Public
     4  * License, v. 2.0. If a copy of the MPL was not distributed with this
     5  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     7 /* A class for lazily constructing an object without sticking it on the heap. */
     9 #ifndef mozilla_Maybe_h
    10 #define mozilla_Maybe_h
    12 #include "mozilla/Alignment.h"
    13 #include "mozilla/Assertions.h"
    15 // For placement new
    16 #include <new>
    18 namespace mozilla {
    20 /*
    21  * Small utility for lazily constructing objects without using dynamic storage.
    22  * When a Maybe<T> is constructed, it is |empty()|, i.e., no value of T has
    23  * been constructed and no T destructor will be called when the Maybe<T> is
    24  * destroyed. Upon calling |construct|, a T object will be constructed with the
    25  * given arguments and that object will be destroyed when the owning Maybe<T>
    26  * is destroyed.
    27  *
    28  * N.B. GCC seems to miss some optimizations with Maybe and may generate extra
    29  * branches/loads/stores. Use with caution on hot paths.
    30  */
    31 template<class T>
    32 class Maybe
    33 {
    34     AlignedStorage2<T> storage;
    35     bool constructed;
    37     T& asT() { return *storage.addr(); }
    39   public:
    40     Maybe() { constructed = false; }
    41     ~Maybe() { if (constructed) asT().~T(); }
    43     bool empty() const { return !constructed; }
    45     void construct() {
    46       MOZ_ASSERT(!constructed);
    47       ::new (storage.addr()) T();
    48       constructed = true;
    49     }
    51     template<class T1>
    52     void construct(const T1& t1) {
    53       MOZ_ASSERT(!constructed);
    54       ::new (storage.addr()) T(t1);
    55       constructed = true;
    56     }
    58     template<class T1, class T2>
    59     void construct(const T1& t1, const T2& t2) {
    60       MOZ_ASSERT(!constructed);
    61       ::new (storage.addr()) T(t1, t2);
    62       constructed = true;
    63     }
    65     template<class T1, class T2, class T3>
    66     void construct(const T1& t1, const T2& t2, const T3& t3) {
    67       MOZ_ASSERT(!constructed);
    68       ::new (storage.addr()) T(t1, t2, t3);
    69       constructed = true;
    70     }
    72     template<class T1, class T2, class T3, class T4>
    73     void construct(const T1& t1, const T2& t2, const T3& t3, const T4& t4) {
    74       MOZ_ASSERT(!constructed);
    75       ::new (storage.addr()) T(t1, t2, t3, t4);
    76       constructed = true;
    77     }
    79     template<class T1, class T2, class T3, class T4, class T5>
    80     void construct(const T1& t1, const T2& t2, const T3& t3, const T4& t4, const T5& t5) {
    81       MOZ_ASSERT(!constructed);
    82       ::new (storage.addr()) T(t1, t2, t3, t4, t5);
    83       constructed = true;
    84     }
    86     template<class T1, class T2, class T3, class T4, class T5,
    87              class T6>
    88     void construct(const T1& t1, const T2& t2, const T3& t3, const T4& t4, const T5& t5,
    89                    const T6& t6) {
    90       MOZ_ASSERT(!constructed);
    91       ::new (storage.addr()) T(t1, t2, t3, t4, t5, t6);
    92       constructed = true;
    93     }
    95     template<class T1, class T2, class T3, class T4, class T5,
    96              class T6, class T7>
    97     void construct(const T1& t1, const T2& t2, const T3& t3, const T4& t4, const T5& t5,
    98                    const T6& t6, const T7& t7) {
    99       MOZ_ASSERT(!constructed);
   100       ::new (storage.addr()) T(t1, t2, t3, t4, t5, t6, t7);
   101       constructed = true;
   102     }
   104     template<class T1, class T2, class T3, class T4, class T5,
   105              class T6, class T7, class T8>
   106     void construct(const T1& t1, const T2& t2, const T3& t3, const T4& t4, const T5& t5,
   107                    const T6& t6, const T7& t7, const T8& t8) {
   108       MOZ_ASSERT(!constructed);
   109       ::new (storage.addr()) T(t1, t2, t3, t4, t5, t6, t7, t8);
   110       constructed = true;
   111     }
   113     template<class T1, class T2, class T3, class T4, class T5,
   114              class T6, class T7, class T8, class T9>
   115     void construct(const T1& t1, const T2& t2, const T3& t3, const T4& t4, const T5& t5,
   116                    const T6& t6, const T7& t7, const T8& t8, const T9& t9) {
   117       MOZ_ASSERT(!constructed);
   118       ::new (storage.addr()) T(t1, t2, t3, t4, t5, t6, t7, t8, t9);
   119       constructed = true;
   120     }
   122     template<class T1, class T2, class T3, class T4, class T5,
   123              class T6, class T7, class T8, class T9, class T10>
   124     void construct(const T1& t1, const T2& t2, const T3& t3, const T4& t4, const T5& t5,
   125                    const T6& t6, const T7& t7, const T8& t8, const T9& t9, const T10& t10) {
   126       MOZ_ASSERT(!constructed);
   127       ::new (storage.addr()) T(t1, t2, t3, t4, t5, t6, t7, t8, t9, t10);
   128       constructed = true;
   129     }
   131     T* addr() {
   132       MOZ_ASSERT(constructed);
   133       return &asT();
   134     }
   136     T& ref() {
   137       MOZ_ASSERT(constructed);
   138       return asT();
   139     }
   141     const T& ref() const {
   142       MOZ_ASSERT(constructed);
   143       return const_cast<Maybe*>(this)->asT();
   144     }
   146     void destroy() {
   147       ref().~T();
   148       constructed = false;
   149     }
   151     void destroyIfConstructed() {
   152       if (!empty())
   153         destroy();
   154     }
   156   private:
   157     Maybe(const Maybe& other) MOZ_DELETE;
   158     const Maybe& operator=(const Maybe& other) MOZ_DELETE;
   159 };
   161 } // namespace mozilla
   163 #endif /* mozilla_Maybe_h */

mercurial