/* * Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. * */ #ifndef SHARE_VM_JFR_UTILITIES_JFRREFCOUNTPOINTER_HPP #define SHARE_VM_JFR_UTILITIES_JFRREFCOUNTPOINTER_HPP #include "jfr/utilities/jfrAllocation.hpp" #include "runtime/atomic.hpp" template class RefCountHandle { template friend class RefCountPointer; private: const T* _ptr; RefCountHandle(const T* ptr) : _ptr(ptr) { assert(_ptr != NULL, "invariant"); _ptr->add_ref(); } public: RefCountHandle() : _ptr(NULL) {} RefCountHandle(const RefCountHandle& rhs) : _ptr(rhs._ptr) { if (_ptr != NULL) { _ptr->add_ref(); } } ~RefCountHandle() { if (_ptr != NULL) { const T* temp = _ptr; _ptr = NULL; temp->remove_ref(); } } // The copy-and-swap idiom upholds reference counting semantics void operator=(RefCountHandle rhs) { const T* temp = rhs._ptr; rhs._ptr = _ptr; _ptr = temp; } bool operator==(const RefCountHandle& rhs) const { return _ptr == rhs._ptr; } bool operator!=(const RefCountHandle& rhs) const { return !operator==(rhs); } bool valid() const { return _ptr != NULL; } const T & operator->() const { return *_ptr; } T& operator->() { return *const_cast(_ptr); } }; class MultiThreadedRefCounter { private: mutable volatile int _refs; public: MultiThreadedRefCounter() : _refs(0) {} void inc() const { Atomic::add(1, &_refs); } bool dec() const { return 0 == Atomic::add((-1), &_refs); } int current() const { return _refs; } }; template class RefCountPointer : public JfrCHeapObj { template friend class RefCountHandle; typedef RefCountHandle > RefHandle; private: const T* _ptr; mutable RefCountImpl _refs; // disallow multiple copies RefCountPointer(const RefCountPointer& rhs); void operator=(const RefCountPointer& rhs); ~RefCountPointer() { assert(_refs.current() == 0, "invariant"); delete const_cast(_ptr); } void add_ref() const { _refs.inc(); } void remove_ref() const { if (_refs.dec()) { delete this; } } RefCountPointer(const T* ptr) : _ptr(ptr), _refs() { assert(_ptr != NULL, "invariant"); } public: const T* operator->() const { return _ptr; } T* operator->() { return const_cast(_ptr); } static RefHandle make(const T* ptr) { assert(ptr != NULL, "invariant"); return RefHandle(new RefCountPointer(ptr)); } }; #endif // SHARE_VM_JFR_UTILITIES_JFRREFCOUNTPOINTER_HPP