Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. //
  2. // Copyright 2013 Francisco Jerez
  3. //
  4. // Permission is hereby granted, free of charge, to any person obtaining a
  5. // copy of this software and associated documentation files (the "Software"),
  6. // to deal in the Software without restriction, including without limitation
  7. // the rights to use, copy, modify, merge, publish, distribute, sublicense,
  8. // and/or sell copies of the Software, and to permit persons to whom the
  9. // Software is furnished to do so, subject to the following conditions:
  10. //
  11. // The above copyright notice and this permission notice shall be included in
  12. // all copies or substantial portions of the Software.
  13. //
  14. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  17. // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
  18. // OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
  19. // ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  20. // OTHER DEALINGS IN THE SOFTWARE.
  21. //
  22.  
  23. #ifndef CLOVER_UTIL_POINTER_HPP
  24. #define CLOVER_UTIL_POINTER_HPP
  25.  
  26. #include <atomic>
  27.  
  28. namespace clover {
  29.    ///
  30.    /// Base class for objects that support reference counting.
  31.    ///
  32.    class ref_counter {
  33.    public:
  34.       ref_counter(unsigned value = 1) : _ref_count(value) {}
  35.  
  36.       unsigned
  37.       ref_count() const {
  38.          return _ref_count;
  39.       }
  40.  
  41.       void
  42.       retain() {
  43.          _ref_count++;
  44.       }
  45.  
  46.       bool
  47.       release() {
  48.          return (--_ref_count) == 0;
  49.       }
  50.  
  51.    private:
  52.       std::atomic<unsigned> _ref_count;
  53.    };
  54.  
  55.    ///
  56.    /// Simple reference to a clover::ref_counter object.  Unlike
  57.    /// clover::intrusive_ptr and clover::intrusive_ref, it does nothing
  58.    /// special when the reference count drops to zero.
  59.    ///
  60.    class ref_holder {
  61.    public:
  62.       ref_holder(ref_counter &o) : p(&o) {
  63.          p->retain();
  64.       }
  65.  
  66.       ref_holder(const ref_holder &ref) :
  67.          ref_holder(*ref.p) {
  68.       }
  69.  
  70.       ref_holder(ref_holder &&ref) :
  71.          p(ref.p) {
  72.          ref.p = NULL;
  73.       }
  74.  
  75.       ~ref_holder() {
  76.          if (p)
  77.             p->release();
  78.       }
  79.  
  80.       ref_holder &
  81.       operator=(ref_holder ref) {
  82.          std::swap(ref.p, p);
  83.          return *this;
  84.       }
  85.  
  86.       bool
  87.       operator==(const ref_holder &ref) const {
  88.          return p == ref.p;
  89.       }
  90.  
  91.       bool
  92.       operator!=(const ref_holder &ref) const {
  93.          return p != ref.p;
  94.       }
  95.  
  96.    private:
  97.       ref_counter *p;
  98.    };
  99.  
  100.    ///
  101.    /// Intrusive smart pointer for objects that implement the
  102.    /// clover::ref_counter interface.
  103.    ///
  104.    template<typename T>
  105.    class intrusive_ptr {
  106.    public:
  107.       intrusive_ptr(T *q = NULL) : p(q) {
  108.          if (p)
  109.             p->retain();
  110.       }
  111.  
  112.       intrusive_ptr(const intrusive_ptr &ptr) :
  113.          intrusive_ptr(ptr.p) {
  114.       }
  115.  
  116.       intrusive_ptr(intrusive_ptr &&ptr) :
  117.          p(ptr.p) {
  118.          ptr.p = NULL;
  119.       }
  120.  
  121.       ~intrusive_ptr() {
  122.          if (p && p->release())
  123.             delete p;
  124.       }
  125.  
  126.       intrusive_ptr &
  127.       operator=(intrusive_ptr ptr) {
  128.          std::swap(ptr.p, p);
  129.          return *this;
  130.       }
  131.  
  132.       bool
  133.       operator==(const intrusive_ptr &ref) const {
  134.          return p == ref.p;
  135.       }
  136.  
  137.       bool
  138.       operator!=(const intrusive_ptr &ref) const {
  139.          return p != ref.p;
  140.       }
  141.  
  142.       T &
  143.       operator*() const {
  144.          return *p;
  145.       }
  146.  
  147.       T *
  148.       operator->() const {
  149.          return p;
  150.       }
  151.  
  152.       T *
  153.       operator()() const {
  154.          return p;
  155.       }
  156.  
  157.       explicit operator bool() const {
  158.          return p;
  159.       }
  160.  
  161.       explicit operator T *() const {
  162.          return p;
  163.       }
  164.  
  165.    private:
  166.       T *p;
  167.    };
  168.  
  169.    ///
  170.    /// Intrusive smart reference for objects that implement the
  171.    /// clover::ref_counter interface.
  172.    ///
  173.    template<typename T>
  174.    class intrusive_ref {
  175.    public:
  176.       intrusive_ref(T &o) : p(&o) {
  177.          p->retain();
  178.       }
  179.  
  180.       intrusive_ref(const intrusive_ref &ref) :
  181.          intrusive_ref(*ref.p) {
  182.       }
  183.  
  184.       intrusive_ref(intrusive_ref &&ref) :
  185.          p(ref.p) {
  186.          ref.p = NULL;
  187.       }
  188.  
  189.       ~intrusive_ref() {
  190.          if (p && p->release())
  191.             delete p;
  192.       }
  193.  
  194.       intrusive_ref &
  195.       operator=(intrusive_ref ref) {
  196.          std::swap(ref.p, p);
  197.          return *this;
  198.       }
  199.  
  200.       bool
  201.       operator==(const intrusive_ref &ref) const {
  202.          return p == ref.p;
  203.       }
  204.  
  205.       bool
  206.       operator!=(const intrusive_ref &ref) const {
  207.          return p != ref.p;
  208.       }
  209.  
  210.       T &
  211.       operator()() const {
  212.          return *p;
  213.       }
  214.  
  215.       operator T &() const {
  216.          return *p;
  217.       }
  218.  
  219.    private:
  220.       T *p;
  221.    };
  222.  
  223.    ///
  224.    /// Initialize a clover::intrusive_ref from a newly created object
  225.    /// using the specified constructor arguments.
  226.    ///
  227.    template<typename T, typename... As>
  228.    intrusive_ref<T>
  229.    create(As &&... as) {
  230.       intrusive_ref<T> ref { *new T(std::forward<As>(as)...) };
  231.       ref().release();
  232.       return ref;
  233.    }
  234.  
  235.    ///
  236.    /// Class that implements the usual pointer interface but in fact
  237.    /// contains the object it seems to be pointing to.
  238.    ///
  239.    template<typename T>
  240.    class pseudo_ptr {
  241.    public:
  242.       pseudo_ptr(T x) : x(x) {
  243.       }
  244.  
  245.       pseudo_ptr(const pseudo_ptr &p) : x(p.x) {
  246.       }
  247.  
  248.       pseudo_ptr &
  249.       operator=(const pseudo_ptr &p) {
  250.          x = p.x;
  251.          return *this;
  252.       }
  253.  
  254.       T &
  255.       operator*() {
  256.          return x;
  257.       }
  258.  
  259.       T *
  260.       operator->() {
  261.          return &x;
  262.       }
  263.  
  264.       explicit operator bool() const {
  265.          return true;
  266.       }
  267.  
  268.    private:
  269.       T x;
  270.    };
  271. }
  272.  
  273. #endif
  274.