LCOV - code coverage report
Current view: top level - mfbt - Scoped.h (source / functions) Hit Total Coverage
Test: output.info Lines: 32 32 100.0 %
Date: 2017-07-14 16:53:18 Functions: 99 195 50.8 %
Legend: Lines: hit not hit

          Line data    Source code
       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/. */
       6             : 
       7             : /* DEPRECATED: Use UniquePtr.h instead. */
       8             : 
       9             : #ifndef mozilla_Scoped_h
      10             : #define mozilla_Scoped_h
      11             : 
      12             : /*
      13             :  * DEPRECATED: Use UniquePtr.h instead.
      14             :  *
      15             :  * Resource Acquisition Is Initialization is a programming idiom used
      16             :  * to write robust code that is able to deallocate resources properly,
      17             :  * even in presence of execution errors or exceptions that need to be
      18             :  * propagated.  The Scoped* classes defined via the |SCOPED_TEMPLATE|
      19             :  * and |MOZ_TYPE_SPECIFIC_SCOPED_POINTER_TEMPLTE| macros perform the
      20             :  * deallocation of the resource they hold once program execution
      21             :  * reaches the end of the scope for which they have been defined.
      22             :  * These macros have been used to automatically close file
      23             :  * descriptors/file handles when reaching the end of the scope,
      24             :  * graphics contexts, etc.
      25             :  *
      26             :  * The general scenario for RAII classes created by the above macros
      27             :  * is the following:
      28             :  *
      29             :  * ScopedClass foo(create_value());
      30             :  * // ... In this scope, |foo| is defined. Use |foo.get()| or |foo.rwget()|
      31             :  *        to access the value.
      32             :  * // ... In case of |return| or |throw|, |foo| is deallocated automatically.
      33             :  * // ... If |foo| needs to be returned or stored, use |foo.forget()|
      34             :  *
      35             :  * Note that the RAII classes defined in this header do _not_ perform any form
      36             :  * of reference-counting or garbage-collection. These classes have exactly two
      37             :  * behaviors:
      38             :  *
      39             :  * - if |forget()| has not been called, the resource is always deallocated at
      40             :  *   the end of the scope;
      41             :  * - if |forget()| has been called, any control on the resource is unbound
      42             :  *   and the resource is not deallocated by the class.
      43             :  */
      44             : 
      45             : #include "mozilla/Assertions.h"
      46             : #include "mozilla/Attributes.h"
      47             : #include "mozilla/GuardObjects.h"
      48             : #include "mozilla/Move.h"
      49             : 
      50             : namespace mozilla {
      51             : 
      52             : /*
      53             :  * Scoped is a helper to create RAII wrappers
      54             :  * Type argument |Traits| is expected to have the following structure:
      55             :  *
      56             :  *   struct Traits
      57             :  *   {
      58             :  *     // Define the type of the value stored in the wrapper
      59             :  *     typedef value_type type;
      60             :  *     // Returns the value corresponding to the uninitialized or freed state
      61             :  *     const static type empty();
      62             :  *     // Release resources corresponding to the wrapped value
      63             :  *     // This function is responsible for not releasing an |empty| value
      64             :  *     const static void release(type);
      65             :  *   }
      66             :  */
      67             : template<typename Traits>
      68             : class MOZ_NON_TEMPORARY_CLASS Scoped
      69             : {
      70             : public:
      71             :   typedef typename Traits::type Resource;
      72             : 
      73        1595 :   explicit Scoped(MOZ_GUARD_OBJECT_NOTIFIER_ONLY_PARAM)
      74        1595 :     : mValue(Traits::empty())
      75             :   {
      76        1595 :     MOZ_GUARD_OBJECT_NOTIFIER_INIT;
      77        1595 :   }
      78             : 
      79       37657 :   explicit Scoped(const Resource& aValue
      80             :                   MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
      81       37657 :     : mValue(aValue)
      82             :   {
      83       37657 :     MOZ_GUARD_OBJECT_NOTIFIER_INIT;
      84       37657 :   }
      85             : 
      86             :   /* Move constructor. */
      87             :   Scoped(Scoped&& aOther
      88             :          MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
      89             :     : mValue(Move(aOther.mValue))
      90             :   {
      91             :     MOZ_GUARD_OBJECT_NOTIFIER_INIT;
      92             :     aOther.mValue = Traits::empty();
      93             :   }
      94             : 
      95       39232 :   ~Scoped() { Traits::release(mValue); }
      96             : 
      97             :   // Constant getter
      98      111517 :   operator const Resource&() const { return mValue; }
      99        2147 :   const Resource& operator->() const { return mValue; }
     100      193467 :   const Resource& get() const { return mValue; }
     101             :   // Non-constant getter.
     102         946 :   Resource& rwget() { return mValue; }
     103             : 
     104             :   /*
     105             :    * Forget the resource.
     106             :    *
     107             :    * Once |forget| has been called, the |Scoped| is neutralized, i.e. it will
     108             :    * have no effect at destruction (unless it is reset to another resource by
     109             :    * |operator=|).
     110             :    *
     111             :    * @return The original resource.
     112             :    */
     113       38208 :   Resource forget()
     114             :   {
     115       38208 :     Resource tmp = mValue;
     116       38208 :     mValue = Traits::empty();
     117       38208 :     return tmp;
     118             :   }
     119             : 
     120             :   /*
     121             :    * Perform immediate clean-up of this |Scoped|.
     122             :    *
     123             :    * If this |Scoped| is currently empty, this method has no effect.
     124             :    */
     125           2 :   void dispose()
     126             :   {
     127           2 :     Traits::release(mValue);
     128           2 :     mValue = Traits::empty();
     129           2 :   }
     130             : 
     131             :   bool operator==(const Resource& aOther) const { return mValue == aOther; }
     132             : 
     133             :   /*
     134             :    * Replace the resource with another resource.
     135             :    *
     136             :    * Calling |operator=| has the side-effect of triggering clean-up. If you do
     137             :    * not want to trigger clean-up, you should first invoke |forget|.
     138             :    *
     139             :    * @return this
     140             :    */
     141           9 :   Scoped& operator=(const Resource& aOther) { return reset(aOther); }
     142             : 
     143          62 :   Scoped& reset(const Resource& aOther)
     144             :   {
     145          62 :     Traits::release(mValue);
     146          62 :     mValue = aOther;
     147          62 :     return *this;
     148             :   }
     149             : 
     150             :   /* Move assignment operator. */
     151             :   Scoped& operator=(Scoped&& aRhs)
     152             :   {
     153             :     MOZ_ASSERT(&aRhs != this, "self-move-assignment not allowed");
     154             :     this->~Scoped();
     155             :     new(this) Scoped(Move(aRhs));
     156             :     return *this;
     157             :   }
     158             : 
     159             : private:
     160             :   explicit Scoped(const Scoped& aValue) = delete;
     161             :   Scoped& operator=(const Scoped& aValue) = delete;
     162             : 
     163             : private:
     164             :   Resource mValue;
     165             :   MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
     166             : };
     167             : 
     168             : /*
     169             :  * SCOPED_TEMPLATE defines a templated class derived from Scoped
     170             :  * This allows to implement templates such as ScopedFreePtr.
     171             :  *
     172             :  * @param name The name of the class to define.
     173             :  * @param Traits A struct implementing clean-up. See the implementations
     174             :  * for more details.
     175             :  */
     176             : #define SCOPED_TEMPLATE(name, Traits)                                         \
     177             : template<typename Type>                                                       \
     178             : struct MOZ_NON_TEMPORARY_CLASS name : public mozilla::Scoped<Traits<Type> >   \
     179             : {                                                                             \
     180             :   typedef mozilla::Scoped<Traits<Type> > Super;                               \
     181             :   typedef typename Super::Resource Resource;                                  \
     182             :   name& operator=(Resource aRhs)                                              \
     183             :   {                                                                           \
     184             :     Super::operator=(aRhs);                                                   \
     185             :     return *this;                                                             \
     186             :   }                                                                           \
     187             :   name& operator=(name&& aRhs)                                                \
     188             :   {                                                                           \
     189             :     Super::operator=(Move(aRhs));                                             \
     190             :     return *this;                                                             \
     191             :   }                                                                           \
     192             :   explicit name(MOZ_GUARD_OBJECT_NOTIFIER_ONLY_PARAM)                         \
     193             :     : Super(MOZ_GUARD_OBJECT_NOTIFIER_ONLY_PARAM_TO_PARENT)                   \
     194             :   {}                                                                          \
     195             :   explicit name(Resource aRhs                                                 \
     196             :                 MOZ_GUARD_OBJECT_NOTIFIER_PARAM)                              \
     197             :     : Super(aRhs                                                              \
     198             :             MOZ_GUARD_OBJECT_NOTIFIER_PARAM_TO_PARENT)                        \
     199             :   {}                                                                          \
     200             :   name(name&& aRhs                                                            \
     201             :        MOZ_GUARD_OBJECT_NOTIFIER_PARAM)                                       \
     202             :     : Super(Move(aRhs)                                                        \
     203             :             MOZ_GUARD_OBJECT_NOTIFIER_PARAM_TO_PARENT)                        \
     204             :   {}                                                                          \
     205             : private:                                                                      \
     206             :   explicit name(name&) = delete;                                              \
     207             :   name& operator=(name&) = delete;                                            \
     208             : };
     209             : 
     210             : /*
     211             :  * MOZ_TYPE_SPECIFIC_SCOPED_POINTER_TEMPLATE makes it easy to create scoped
     212             :  * pointers for types with custom deleters; just overload
     213             :  * TypeSpecificDelete(T*) in the same namespace as T to call the deleter for
     214             :  * type T.
     215             :  *
     216             :  * @param name The name of the class to define.
     217             :  * @param Type A struct implementing clean-up. See the implementations
     218             :  * for more details.
     219             :  * *param Deleter The function that is used to delete/destroy/free a
     220             :  *        non-null value of Type*.
     221             :  *
     222             :  * Example:
     223             :  *
     224             :  *   MOZ_TYPE_SPECIFIC_SCOPED_POINTER_TEMPLATE(ScopedPRFileDesc, PRFileDesc, \
     225             :  *                                             PR_Close)
     226             :  *   ...
     227             :  *   {
     228             :  *       ScopedPRFileDesc file(PR_OpenFile(...));
     229             :  *       ...
     230             :  *   } // file is closed with PR_Close here
     231             :  */
     232             : #define MOZ_TYPE_SPECIFIC_SCOPED_POINTER_TEMPLATE(name, Type, Deleter) \
     233             : template <> inline void TypeSpecificDelete(Type* aValue) { Deleter(aValue); } \
     234             : typedef ::mozilla::TypeSpecificScopedPointer<Type> name;
     235             : 
     236             : template <typename T> void TypeSpecificDelete(T* aValue);
     237             : 
     238             : template <typename T>
     239             : struct TypeSpecificScopedPointerTraits
     240             : {
     241             :   typedef T* type;
     242           3 :   static type empty() { return nullptr; }
     243           6 :   static void release(type aValue)
     244             :   {
     245           6 :     if (aValue) {
     246           2 :       TypeSpecificDelete(aValue);
     247             :     }
     248           6 :   }
     249             : };
     250             : 
     251           9 : SCOPED_TEMPLATE(TypeSpecificScopedPointer, TypeSpecificScopedPointerTraits)
     252             : 
     253             : } /* namespace mozilla */
     254             : 
     255             : #endif /* mozilla_Scoped_h */

Generated by: LCOV version 1.13