?login_element?

Subversion Repositories NedoOS

Rev

Blame | Last modification | View Log | Download

  1. // https://github.com/vinniefalco/LuaBridge
  2. // Copyright 2021, Stefan Frings
  3. // Copyright 2019, Dmitry Tarakanov
  4. // Copyright 2012, Vinnie Falco <vinnie.falco@gmail.com>
  5. // Copyright 2007, Nathan Reed
  6. // SPDX-License-Identifier: MIT
  7.  
  8. #pragma once
  9.  
  10. #include <cassert>
  11. #include <unordered_map>
  12. #include <utility>
  13.  
  14. namespace luabridge {
  15.  
  16. namespace detail {
  17.  
  18. //==============================================================================
  19. /**
  20.   Support for our RefCountedPtr.
  21. */
  22. struct RefCountedPtrBase
  23. {
  24.     // Declaration of container for the refcounts
  25.     typedef std::unordered_map<const void*, int> RefCountsType;
  26.  
  27. protected:
  28.     RefCountsType& getRefCounts() const
  29.     {
  30.         static RefCountsType refcounts;
  31.         return refcounts;
  32.     }
  33. };
  34.  
  35. } // namespace detail
  36.  
  37. //==============================================================================
  38. /**
  39.   A reference counted smart pointer.
  40.  
  41.   The api is compatible with boost::RefCountedPtr and std::RefCountedPtr, in the
  42.   sense that it implements a strict subset of the functionality.
  43.  
  44.   This implementation uses a hash table to look up the reference count
  45.   associated with a particular pointer.
  46.  
  47.   @tparam T The class type.
  48.  
  49.   @todo Decompose RefCountedPtr using a policy. At a minimum, the underlying
  50.         reference count should be policy based (to support atomic operations)
  51.         and the delete behavior should be policy based (to support custom
  52.         disposal methods).
  53.  
  54.   @todo Provide an intrusive version of RefCountedPtr.
  55. */
  56. template<class T>
  57. class RefCountedPtr : private detail::RefCountedPtrBase
  58. {
  59. public:
  60.     template<typename Other>
  61.     struct rebind
  62.     {
  63.         typedef RefCountedPtr<Other> other;
  64.     };
  65.  
  66.     /** Construct as nullptr or from existing pointer to T.
  67.  
  68.         @param p The optional, existing pointer to assign from.
  69.     */
  70.     RefCountedPtr(T* const p = nullptr) : m_p(p)
  71.     {
  72.         if (m_p)
  73.         {
  74.             ++getRefCounts()[m_p];
  75.         }
  76.     }
  77.  
  78.     /** Construct from another RefCountedPtr.
  79.  
  80.         @param rhs The RefCountedPtr to assign from.
  81.     */
  82.     RefCountedPtr(RefCountedPtr<T> const& rhs) : RefCountedPtr(rhs.get()) {}
  83.  
  84.     /** Construct from a RefCountedPtr of a different type.
  85.  
  86.         @invariant A pointer to U must be convertible to a pointer to T.
  87.  
  88.         @tparam U   The other object type.
  89.         @param  rhs The RefCountedPtr to assign from.
  90.     */
  91.     template<typename U>
  92.     RefCountedPtr(RefCountedPtr<U> const& rhs) : RefCountedPtr(rhs.get())
  93.     {
  94.     }
  95.  
  96.     /** Release the object.
  97.  
  98.         If there are no more references then the object is deleted.
  99.     */
  100.     ~RefCountedPtr() { reset(); }
  101.  
  102.     /** Assign from another RefCountedPtr.
  103.  
  104.         @param  rhs The RefCountedPtr to assign from.
  105.         @returns     A reference to the RefCountedPtr.
  106.     */
  107.     RefCountedPtr<T>& operator=(RefCountedPtr<T> const& rhs)
  108.     {
  109.         // NOTE Self assignment is handled gracefully
  110.         *this = rhs.get();
  111.         return *this;
  112.     }
  113.  
  114.     /** Assign from another RefCountedPtr of a different type.
  115.  
  116.         @note A pointer to U must be convertible to a pointer to T.
  117.  
  118.         @tparam U   The other object type.
  119.         @param  rhs The other RefCountedPtr to assign from.
  120.         @returns     A reference to the RefCountedPtr.
  121.     */
  122.     template<typename U>
  123.     RefCountedPtr<T>& operator=(RefCountedPtr<U> const& rhs)
  124.     {
  125.         // NOTE Self assignment is handled gracefully
  126.         *this = rhs.get();
  127.         return *this;
  128.     }
  129.  
  130.     RefCountedPtr<T>& operator=(T* const p)
  131.     {
  132.         if (p != m_p)
  133.         {
  134.             RefCountedPtr<T> tmp(p);
  135.             std::swap(m_p, tmp.m_p);
  136.         }
  137.  
  138.         return *this;
  139.     }
  140.  
  141.     /** Retrieve the raw pointer.
  142.  
  143.         @returns A pointer to the object.
  144.     */
  145.     T* get() const { return m_p; }
  146.  
  147.     /** Retrieve the raw pointer by conversion.
  148.  
  149.         @returns A pointer to the object.
  150.     */
  151.     operator T*() const { return m_p; }
  152.  
  153.     /** Retrieve the raw pointer.
  154.  
  155.         @returns A pointer to the object.
  156.     */
  157.     T* operator*() const { return m_p; }
  158.  
  159.     /** Retrieve the raw pointer.
  160.  
  161.         @returns A pointer to the object.
  162.     */
  163.     T* operator->() const { return m_p; }
  164.  
  165.     /** Determine the number of references.
  166.  
  167.         @note This is not thread-safe.
  168.  
  169.         @returns The number of active references.
  170.     */
  171.     RefCountsType::mapped_type use_count() const
  172.     {
  173.         if (!m_p)
  174.         {
  175.             return 0;
  176.         }
  177.  
  178.         const auto itCounter = getRefCounts().find(m_p);
  179.         assert(itCounter != getRefCounts().end());
  180.         assert(itCounter->second > 0);
  181.  
  182.         return itCounter->second;
  183.     }
  184.  
  185.     /** Release the pointer.
  186.  
  187.         The reference count is decremented. If the reference count reaches
  188.         zero, the object is deleted.
  189.     */
  190.     void reset()
  191.     {
  192.         if (m_p)
  193.         {
  194.             const auto itCounter = getRefCounts().find(m_p);
  195.             assert(itCounter != getRefCounts().end());
  196.             assert(itCounter->second > 0);
  197.  
  198.             if (--itCounter->second == 0)
  199.             {
  200.                 delete m_p;
  201.                 getRefCounts().erase(itCounter);
  202.             }
  203.  
  204.             m_p = nullptr;
  205.         }
  206.     }
  207.  
  208. private:
  209.     T* m_p;
  210. };
  211.  
  212. //==============================================================================
  213.  
  214. // forward declaration
  215. template<class T>
  216. struct ContainerTraits;
  217.  
  218. template<class T>
  219. struct ContainerTraits<RefCountedPtr<T>>
  220. {
  221.     typedef T Type;
  222.  
  223.     static T* get(RefCountedPtr<T> const& c) { return c.get(); }
  224. };
  225.  
  226. } // namespace luabridge
  227.