LCOV - code coverage report
Current view: top level - gfx/skia/skia/include/core - SkTLazy.h (source / functions) Hit Total Coverage
Test: output.info Lines: 9 33 27.3 %
Date: 2017-07-14 16:53:18 Functions: 7 75 9.3 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  * Copyright 2011 Google Inc.
       3             :  *
       4             :  * Use of this source code is governed by a BSD-style license that can be
       5             :  * found in the LICENSE file.
       6             :  */
       7             : 
       8             : #ifndef SkTLazy_DEFINED
       9             : #define SkTLazy_DEFINED
      10             : 
      11             : #include "../private/SkTemplates.h"
      12             : #include "SkTypes.h"
      13             : #include <new>
      14             : #include <utility>
      15             : 
      16             : /**
      17             :  *  Efficient way to defer allocating/initializing a class until it is needed
      18             :  *  (if ever).
      19             :  */
      20             : template <typename T> class SkTLazy {
      21             : public:
      22        1259 :     SkTLazy() : fPtr(nullptr) {}
      23             : 
      24             :     explicit SkTLazy(const T* src)
      25             :         : fPtr(src ? new (fStorage.get()) T(*src) : nullptr) {}
      26             : 
      27             :     SkTLazy(const SkTLazy& src) : fPtr(nullptr) { *this = src; }
      28             : 
      29        1259 :     ~SkTLazy() {
      30        1259 :         if (this->isValid()) {
      31           0 :             fPtr->~T();
      32             :         }
      33        1259 :     }
      34             : 
      35             :     SkTLazy& operator=(const SkTLazy& src) {
      36             :         if (src.isValid()) {
      37             :             this->set(*src.get());
      38             :         } else {
      39             :             this->reset();
      40             :         }
      41             :         return *this;
      42             :     }
      43             : 
      44             :     /**
      45             :      *  Return a pointer to an instance of the class initialized with 'args'.
      46             :      *  If a previous instance had been initialized (either from init() or
      47             :      *  set()) it will first be destroyed, so that a freshly initialized
      48             :      *  instance is always returned.
      49             :      */
      50           0 :     template <typename... Args> T* init(Args&&... args) {
      51           0 :         if (this->isValid()) {
      52           0 :             fPtr->~T();
      53             :         }
      54           0 :         fPtr = new (SkTCast<T*>(fStorage.get())) T(std::forward<Args>(args)...);
      55           0 :         return fPtr;
      56             :     }
      57             : 
      58             :     /**
      59             :      *  Copy src into this, and return a pointer to a copy of it. Note this
      60             :      *  will always return the same pointer, so if it is called on a lazy that
      61             :      *  has already been initialized, then this will copy over the previous
      62             :      *  contents.
      63             :      */
      64           0 :     T* set(const T& src) {
      65           0 :         if (this->isValid()) {
      66           0 :             *fPtr = src;
      67             :         } else {
      68           0 :             fPtr = new (SkTCast<T*>(fStorage.get())) T(src);
      69             :         }
      70           0 :         return fPtr;
      71             :     }
      72             : 
      73             :     /**
      74             :      * Destroy the lazy object (if it was created via init() or set())
      75             :      */
      76           0 :     void reset() {
      77           0 :         if (this->isValid()) {
      78           0 :             fPtr->~T();
      79           0 :             fPtr = nullptr;
      80             :         }
      81           0 :     }
      82             : 
      83             :     /**
      84             :      *  Returns true if a valid object has been initialized in the SkTLazy,
      85             :      *  false otherwise.
      86             :      */
      87        1259 :     bool isValid() const { return SkToBool(fPtr); }
      88             : 
      89             :     /**
      90             :      * Returns the object. This version should only be called when the caller
      91             :      * knows that the object has been initialized.
      92             :      */
      93           0 :     T* get() const { SkASSERT(this->isValid()); return fPtr; }
      94             : 
      95             :     /**
      96             :      * Like above but doesn't assert if object isn't initialized (in which case
      97             :      * nullptr is returned).
      98             :      */
      99           0 :     T* getMaybeNull() const { return fPtr; }
     100             : 
     101             : private:
     102             :     SkAlignedSTStorage<1, T> fStorage;
     103             :     T*                       fPtr; // nullptr or fStorage
     104             : };
     105             : 
     106             : /**
     107             :  * A helper built on top of SkTLazy to do copy-on-first-write. The object is initialized
     108             :  * with a const pointer but provides a non-const pointer accessor. The first time the
     109             :  * accessor is called (if ever) the object is cloned.
     110             :  *
     111             :  * In the following example at most one copy of constThing is made:
     112             :  *
     113             :  * SkTCopyOnFirstWrite<Thing> thing(&constThing);
     114             :  * ...
     115             :  * function_that_takes_a_const_thing_ptr(thing); // constThing is passed
     116             :  * ...
     117             :  * if (need_to_modify_thing()) {
     118             :  *    thing.writable()->modifyMe(); // makes a copy of constThing
     119             :  * }
     120             :  * ...
     121             :  * x = thing->readSomething();
     122             :  * ...
     123             :  * if (need_to_modify_thing_now()) {
     124             :  *    thing.writable()->changeMe(); // makes a copy of constThing if we didn't call modifyMe()
     125             :  * }
     126             :  *
     127             :  * consume_a_thing(thing); // could be constThing or a modified copy.
     128             :  */
     129             : template <typename T>
     130         516 : class SkTCopyOnFirstWrite {
     131             : public:
     132         516 :     SkTCopyOnFirstWrite(const T& initial) : fObj(&initial) {}
     133             : 
     134             :     SkTCopyOnFirstWrite(const T* initial) : fObj(initial) {}
     135             : 
     136             :     // Constructor for delayed initialization.
     137             :     SkTCopyOnFirstWrite() : fObj(nullptr) {}
     138             : 
     139             :     // Should only be called once, and only if the default constructor was used.
     140             :     void init(const T& initial) {
     141             :         SkASSERT(nullptr == fObj);
     142             :         SkASSERT(!fLazy.isValid());
     143             :         fObj = &initial;
     144             :     }
     145             : 
     146             :     /**
     147             :      * Returns a writable T*. The first time this is called the initial object is cloned.
     148             :      */
     149           0 :     T* writable() {
     150           0 :         SkASSERT(fObj);
     151           0 :         if (!fLazy.isValid()) {
     152           0 :             fLazy.set(*fObj);
     153           0 :             fObj = fLazy.get();
     154             :         }
     155           0 :         return const_cast<T*>(fObj);
     156             :     }
     157             : 
     158             :     /**
     159             :      * Operators for treating this as though it were a const pointer.
     160             :      */
     161             : 
     162         528 :     const T *operator->() const { return fObj; }
     163             : 
     164             :     operator const T*() const { return fObj; }
     165             : 
     166        1118 :     const T& operator *() const { return *fObj; }
     167             : 
     168             : private:
     169             :     const T*    fObj;
     170             :     SkTLazy<T>  fLazy;
     171             : };
     172             : 
     173             : #endif

Generated by: LCOV version 1.13