1 /*
   2  * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  *
  23  */
  24 
  25 #ifndef SHARE_VM_JFR_UTILITIES_JFRREFCOUNTPOINTER_HPP
  26 #define SHARE_VM_JFR_UTILITIES_JFRREFCOUNTPOINTER_HPP
  27 
  28 #include "jfr/utilities/jfrAllocation.hpp"
  29 #include "runtime/atomic.hpp"
  30 
  31 template <typename T>
  32 class RefCountHandle {
  33   template <typename, typename>
  34   friend class RefCountPointer;
  35  private:
  36   const T* _ptr;
  37 
  38   RefCountHandle(const T* ptr) : _ptr(ptr) {
  39     assert(_ptr != NULL, "invariant");
  40     _ptr->add_ref();
  41   }
  42 
  43  public:
  44   RefCountHandle() : _ptr(NULL) {}
  45 
  46   RefCountHandle(const RefCountHandle<T>& rhs) : _ptr(rhs._ptr) {
  47     if (_ptr != NULL) {
  48       _ptr->add_ref();
  49     }
  50   }
  51 
  52   ~RefCountHandle() {
  53     if (_ptr != NULL) {
  54       const T* temp = _ptr;
  55       _ptr = NULL;
  56       temp->remove_ref();
  57     }
  58   }
  59 
  60   // The copy-and-swap idiom upholds reference counting semantics
  61   void operator=(RefCountHandle<T> rhs) {
  62     const T* temp = rhs._ptr;
  63     rhs._ptr = _ptr;
  64     _ptr = temp;
  65   }
  66 
  67   bool operator==(const RefCountHandle<T>& rhs) const {
  68     return _ptr == rhs._ptr;
  69   }
  70 
  71   bool operator!=(const RefCountHandle<T>& rhs) const {
  72     return !operator==(rhs);
  73   }
  74 
  75   bool valid() const {
  76     return _ptr != NULL;
  77   }
  78 
  79   const T & operator->() const {
  80     return *_ptr;
  81   }
  82 
  83   T& operator->() {
  84     return *const_cast<T*>(_ptr);
  85   }
  86 };
  87 
  88 class MultiThreadedRefCounter {
  89  private:
  90   mutable volatile int _refs;
  91  public:
  92   MultiThreadedRefCounter() : _refs(0) {}
  93 
  94   void inc() const {
  95     Atomic::add(1, &_refs);
  96   }
  97 
  98   bool dec() const {
  99     return 0 == Atomic::add((-1), &_refs);
 100   }
 101 
 102   int current() const {
 103    return _refs;
 104   }
 105 };
 106 
 107 template <typename T, typename RefCountImpl = MultiThreadedRefCounter>
 108 class RefCountPointer : public JfrCHeapObj {
 109   template <typename>
 110   friend class RefCountHandle;
 111   typedef RefCountHandle<RefCountPointer<T, RefCountImpl> > RefHandle;
 112  private:
 113   const T* _ptr;
 114   mutable RefCountImpl _refs;
 115 
 116   // disallow multiple copies
 117   RefCountPointer(const RefCountPointer<T, RefCountImpl>& rhs);
 118   void operator=(const RefCountPointer<T, RefCountImpl>& rhs);
 119 
 120   ~RefCountPointer() {
 121     assert(_refs.current() == 0, "invariant");
 122     delete const_cast<T*>(_ptr);
 123   }
 124 
 125   void add_ref() const {
 126     _refs.inc();
 127   }
 128 
 129   void remove_ref() const {
 130     if (_refs.dec()) {
 131       delete this;
 132     }
 133   }
 134 
 135   RefCountPointer(const T* ptr) : _ptr(ptr), _refs() {
 136     assert(_ptr != NULL, "invariant");
 137   }
 138 
 139  public:
 140   const T* operator->() const {
 141     return _ptr;
 142   }
 143 
 144   T* operator->() {
 145     return const_cast<T*>(_ptr);
 146   }
 147 
 148   static RefHandle make(const T* ptr) {
 149     assert(ptr != NULL, "invariant");
 150     return RefHandle(new RefCountPointer<T, RefCountImpl>(ptr));
 151   }
 152 };
 153 
 154 #endif // SHARE_VM_JFR_UTILITIES_JFRREFCOUNTPOINTER_HPP